avoid annexFileMode special case
This makes annexFileMode be just an application of setAnnexPerm', which avoids having 2 functions that do different versions of the same thing. Fixes some buggy behavior for some combinations of core.sharedRepository and umask. Sponsored-by: Jack Hill on Patreon
This commit is contained in:
parent
67f8268b3f
commit
aff37fc208
13 changed files with 82 additions and 69 deletions
|
@ -102,6 +102,7 @@ import Logs.Location
|
||||||
import Utility.InodeCache
|
import Utility.InodeCache
|
||||||
import Utility.CopyFile
|
import Utility.CopyFile
|
||||||
import Utility.Metered
|
import Utility.Metered
|
||||||
|
import Utility.FileMode
|
||||||
import qualified Utility.RawFilePath as R
|
import qualified Utility.RawFilePath as R
|
||||||
|
|
||||||
import qualified System.FilePath.ByteString as P
|
import qualified System.FilePath.ByteString as P
|
||||||
|
@ -171,7 +172,7 @@ lockContentForRemoval key fallback a = lockContentUsing lock key fallback $
|
||||||
type ContentLocker = RawFilePath -> Maybe LockFile -> (Annex (Maybe LockHandle), Maybe (Annex (Maybe LockHandle)))
|
type ContentLocker = RawFilePath -> Maybe LockFile -> (Annex (Maybe LockHandle), Maybe (Annex (Maybe LockHandle)))
|
||||||
|
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
posixLocker :: (Maybe FileMode -> LockFile -> Annex (Maybe LockHandle)) -> LockFile -> Annex (Maybe LockHandle)
|
posixLocker :: (Maybe ModeSetter -> LockFile -> Annex (Maybe LockHandle)) -> LockFile -> Annex (Maybe LockHandle)
|
||||||
posixLocker takelock lockfile = do
|
posixLocker takelock lockfile = do
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
modifyContentDirWhenExists lockfile $
|
modifyContentDirWhenExists lockfile $
|
||||||
|
|
|
@ -36,7 +36,7 @@ lockFileCached file = go =<< fromLockCache file
|
||||||
go Nothing = do
|
go Nothing = do
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
lockhandle <- noUmask mode $ lockShared (Just mode) file
|
lockhandle <- lockShared (Just mode) file
|
||||||
#else
|
#else
|
||||||
lockhandle <- liftIO $ waitToLock $ lockShared file
|
lockhandle <- liftIO $ waitToLock $ lockShared file
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,7 +69,7 @@ withSharedLock lockfile a = debugLocks $ do
|
||||||
bracket (lock mode lockfile) (liftIO . dropLock) (const a)
|
bracket (lock mode lockfile) (liftIO . dropLock) (const a)
|
||||||
where
|
where
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
lock mode = noUmask mode . lockShared (Just mode)
|
lock mode = lockShared (Just mode)
|
||||||
#else
|
#else
|
||||||
lock _mode = liftIO . waitToLock . lockShared
|
lock _mode = liftIO . waitToLock . lockShared
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,7 +90,7 @@ takeExclusiveLock lockfile = debugLocks $ do
|
||||||
lock mode lockfile
|
lock mode lockfile
|
||||||
where
|
where
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
lock mode = noUmask mode . lockExclusive (Just mode)
|
lock mode = lockExclusive (Just mode)
|
||||||
#else
|
#else
|
||||||
lock _mode = liftIO . waitToLock . lockExclusive
|
lock _mode = liftIO . waitToLock . lockExclusive
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,7 +104,7 @@ tryExclusiveLock lockfile a = debugLocks $ do
|
||||||
bracket (lock mode lockfile) (liftIO . unlock) go
|
bracket (lock mode lockfile) (liftIO . unlock) go
|
||||||
where
|
where
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
lock mode = noUmask mode . tryLockExclusive (Just mode)
|
lock mode = tryLockExclusive (Just mode)
|
||||||
#else
|
#else
|
||||||
lock _mode = liftIO . lockExclusive
|
lock _mode = liftIO . lockExclusive
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,6 +26,7 @@ import qualified Annex
|
||||||
import qualified Utility.LockPool.Posix as Posix
|
import qualified Utility.LockPool.Posix as Posix
|
||||||
import qualified Utility.LockPool.PidLock as Pid
|
import qualified Utility.LockPool.PidLock as Pid
|
||||||
import qualified Utility.LockPool.LockHandle as H
|
import qualified Utility.LockPool.LockHandle as H
|
||||||
|
import Utility.FileMode
|
||||||
import Utility.LockPool.LockHandle (LockHandle, dropLock)
|
import Utility.LockPool.LockHandle (LockHandle, dropLock)
|
||||||
import Utility.LockFile.Posix (openLockFile)
|
import Utility.LockFile.Posix (openLockFile)
|
||||||
import Utility.LockPool.STM (LockFile, LockMode(..))
|
import Utility.LockPool.STM (LockFile, LockMode(..))
|
||||||
|
@ -36,16 +37,16 @@ import Git.Quote
|
||||||
|
|
||||||
import System.Posix
|
import System.Posix
|
||||||
|
|
||||||
lockShared :: Maybe FileMode -> LockFile -> Annex LockHandle
|
lockShared :: Maybe ModeSetter -> LockFile -> Annex LockHandle
|
||||||
lockShared m f = pidLock m f LockShared $ Posix.lockShared m f
|
lockShared m f = pidLock m f LockShared $ Posix.lockShared m f
|
||||||
|
|
||||||
lockExclusive :: Maybe FileMode -> LockFile -> Annex LockHandle
|
lockExclusive :: Maybe ModeSetter -> LockFile -> Annex LockHandle
|
||||||
lockExclusive m f = pidLock m f LockExclusive $ Posix.lockExclusive m f
|
lockExclusive m f = pidLock m f LockExclusive $ Posix.lockExclusive m f
|
||||||
|
|
||||||
tryLockShared :: Maybe FileMode -> LockFile -> Annex (Maybe LockHandle)
|
tryLockShared :: Maybe ModeSetter -> LockFile -> Annex (Maybe LockHandle)
|
||||||
tryLockShared m f = tryPidLock m f LockShared $ Posix.tryLockShared m f
|
tryLockShared m f = tryPidLock m f LockShared $ Posix.tryLockShared m f
|
||||||
|
|
||||||
tryLockExclusive :: Maybe FileMode -> LockFile -> Annex (Maybe LockHandle)
|
tryLockExclusive :: Maybe ModeSetter -> LockFile -> Annex (Maybe LockHandle)
|
||||||
tryLockExclusive m f = tryPidLock m f LockExclusive $ Posix.tryLockExclusive m f
|
tryLockExclusive m f = tryPidLock m f LockExclusive $ Posix.tryLockExclusive m f
|
||||||
|
|
||||||
checkLocked :: LockFile -> Annex (Maybe Bool)
|
checkLocked :: LockFile -> Annex (Maybe Bool)
|
||||||
|
@ -68,7 +69,7 @@ pidLockCheck :: IO a -> (LockFile -> IO a) -> Annex a
|
||||||
pidLockCheck posixcheck pidcheck = debugLocks $
|
pidLockCheck posixcheck pidcheck = debugLocks $
|
||||||
liftIO . maybe posixcheck pidcheck =<< pidLockFile
|
liftIO . maybe posixcheck pidcheck =<< pidLockFile
|
||||||
|
|
||||||
pidLock :: Maybe FileMode -> LockFile -> LockMode -> IO LockHandle -> Annex LockHandle
|
pidLock :: Maybe ModeSetter -> LockFile -> LockMode -> IO LockHandle -> Annex LockHandle
|
||||||
pidLock m f lockmode posixlock = debugLocks $ go =<< pidLockFile
|
pidLock m f lockmode posixlock = debugLocks $ go =<< pidLockFile
|
||||||
where
|
where
|
||||||
go Nothing = liftIO posixlock
|
go Nothing = liftIO posixlock
|
||||||
|
@ -77,7 +78,7 @@ pidLock m f lockmode posixlock = debugLocks $ go =<< pidLockFile
|
||||||
liftIO $ dummyPosixLock m f
|
liftIO $ dummyPosixLock m f
|
||||||
Pid.waitLock f lockmode timeout pidlock (warning . UnquotedString)
|
Pid.waitLock f lockmode timeout pidlock (warning . UnquotedString)
|
||||||
|
|
||||||
tryPidLock :: Maybe FileMode -> LockFile -> LockMode -> IO (Maybe LockHandle) -> Annex (Maybe LockHandle)
|
tryPidLock :: Maybe ModeSetter -> LockFile -> LockMode -> IO (Maybe LockHandle) -> Annex (Maybe LockHandle)
|
||||||
tryPidLock m f lockmode posixlock = debugLocks $ liftIO . go =<< pidLockFile
|
tryPidLock m f lockmode posixlock = debugLocks $ liftIO . go =<< pidLockFile
|
||||||
where
|
where
|
||||||
go Nothing = posixlock
|
go Nothing = posixlock
|
||||||
|
@ -88,5 +89,5 @@ tryPidLock m f lockmode posixlock = debugLocks $ liftIO . go =<< pidLockFile
|
||||||
-- The posix lock file is created even when using pid locks, in order to
|
-- The posix lock file is created even when using pid locks, in order to
|
||||||
-- avoid complicating any code that might expect to be able to see that
|
-- avoid complicating any code that might expect to be able to see that
|
||||||
-- lock file. But, it's not locked.
|
-- lock file. But, it's not locked.
|
||||||
dummyPosixLock :: Maybe FileMode -> LockFile -> IO ()
|
dummyPosixLock :: Maybe ModeSetter -> LockFile -> IO ()
|
||||||
dummyPosixLock m f = bracket (openLockFile ReadLock m f) closeFd (const noop)
|
dummyPosixLock m f = bracket (openLockFile ReadLock m f) closeFd (const noop)
|
||||||
|
|
|
@ -15,7 +15,6 @@ module Annex.Perms (
|
||||||
annexFileMode,
|
annexFileMode,
|
||||||
createAnnexDirectory,
|
createAnnexDirectory,
|
||||||
createWorkTreeDirectory,
|
createWorkTreeDirectory,
|
||||||
noUmask,
|
|
||||||
freezeContent,
|
freezeContent,
|
||||||
freezeContent',
|
freezeContent',
|
||||||
freezeContent'',
|
freezeContent'',
|
||||||
|
@ -60,24 +59,26 @@ setAnnexDirPerm = setAnnexPerm True
|
||||||
- don't change the mode, but with core.sharedRepository set,
|
- don't change the mode, but with core.sharedRepository set,
|
||||||
- allow the group to write, etc. -}
|
- allow the group to write, etc. -}
|
||||||
setAnnexPerm :: Bool -> RawFilePath -> Annex ()
|
setAnnexPerm :: Bool -> RawFilePath -> Annex ()
|
||||||
setAnnexPerm = setAnnexPerm' Nothing
|
setAnnexPerm isdir file = setAnnexPerm' Nothing isdir >>= \go -> liftIO (go file)
|
||||||
|
|
||||||
setAnnexPerm' :: Maybe ([FileMode] -> FileMode -> FileMode) -> Bool -> RawFilePath -> Annex ()
|
setAnnexPerm' :: Maybe ([FileMode] -> FileMode -> FileMode) -> Bool -> Annex (RawFilePath -> IO ())
|
||||||
setAnnexPerm' modef isdir file = unlessM crippledFileSystem $
|
setAnnexPerm' modef isdir = ifM crippledFileSystem
|
||||||
withShared go
|
( return (const noop)
|
||||||
|
, withShared $ \s -> return $ \file -> go s file
|
||||||
|
)
|
||||||
where
|
where
|
||||||
go GroupShared = void $ liftIO $ tryIO $ modifyFileMode file $ modef' $
|
go GroupShared file = void $ tryIO $ modifyFileMode file $ modef' $
|
||||||
groupSharedModes ++
|
groupSharedModes ++
|
||||||
if isdir then [ ownerExecuteMode, groupExecuteMode ] else []
|
if isdir then [ ownerExecuteMode, groupExecuteMode ] else []
|
||||||
go AllShared = void $ liftIO $ tryIO $ modifyFileMode file $ modef' $
|
go AllShared file = void $ tryIO $ modifyFileMode file $ modef' $
|
||||||
readModes ++
|
readModes ++
|
||||||
[ ownerWriteMode, groupWriteMode ] ++
|
[ ownerWriteMode, groupWriteMode ] ++
|
||||||
if isdir then executeModes else []
|
if isdir then executeModes else []
|
||||||
go UnShared = case modef of
|
go UnShared file = case modef of
|
||||||
Nothing -> noop
|
Nothing -> noop
|
||||||
Just f -> void $ liftIO $ tryIO $
|
Just f -> void $ tryIO $
|
||||||
modifyFileMode file $ f []
|
modifyFileMode file $ f []
|
||||||
go (UmaskShared n) = void $ liftIO $ tryIO $ R.setFileMode file $
|
go (UmaskShared n) file = void $ tryIO $ R.setFileMode file $
|
||||||
if isdir then umaskSharedDirectory n else n
|
if isdir then umaskSharedDirectory n else n
|
||||||
modef' = fromMaybe addModes modef
|
modef' = fromMaybe addModes modef
|
||||||
|
|
||||||
|
@ -96,20 +97,19 @@ resetAnnexPerm :: Bool -> RawFilePath -> Annex ()
|
||||||
resetAnnexPerm isdir file = unlessM crippledFileSystem $ do
|
resetAnnexPerm isdir file = unlessM crippledFileSystem $ do
|
||||||
defmode <- liftIO defaultFileMode
|
defmode <- liftIO defaultFileMode
|
||||||
let modef moremodes _oldmode = addModes moremodes defmode
|
let modef moremodes _oldmode = addModes moremodes defmode
|
||||||
setAnnexPerm' (Just modef) isdir file
|
setAnnexPerm' (Just modef) isdir >>= \go -> liftIO (go file)
|
||||||
|
|
||||||
{- Gets the appropriate mode to use for creating a file in the annex
|
{- Creates a ModeSetter which can be used for creating a file in the annex
|
||||||
- (other than content files, which are locked down more). The umask is not
|
- (other than content files, which are locked down more). -}
|
||||||
- taken into account; this is for use with actions that create the file
|
annexFileMode :: Annex ModeSetter
|
||||||
- and apply the umask automatically. -}
|
annexFileMode = do
|
||||||
annexFileMode :: Annex FileMode
|
modesetter <- setAnnexPerm' Nothing False
|
||||||
annexFileMode = withShared (pure . go)
|
withShared (\s -> pure $ mk s modesetter)
|
||||||
where
|
where
|
||||||
go GroupShared = sharedmode
|
mk GroupShared = ModeSetter stdFileMode
|
||||||
go AllShared = combineModes (sharedmode:readModes)
|
mk AllShared = ModeSetter stdFileMode
|
||||||
go UnShared = stdFileMode
|
mk UnShared = ModeSetter stdFileMode
|
||||||
go (UmaskShared n) = n
|
mk (UmaskShared mode) = ModeSetter mode
|
||||||
sharedmode = combineModes groupSharedModes
|
|
||||||
|
|
||||||
{- Creates a directory inside the gitAnnexDir (or possibly the dbdir),
|
{- Creates a directory inside the gitAnnexDir (or possibly the dbdir),
|
||||||
- creating any parent directories up to and including the gitAnnexDir.
|
- creating any parent directories up to and including the gitAnnexDir.
|
||||||
|
|
|
@ -311,7 +311,7 @@ sshCleanup = mapM_ cleanup =<< enumSocketFiles
|
||||||
let lockfile = socket2lock socketfile
|
let lockfile = socket2lock socketfile
|
||||||
unlockFile lockfile
|
unlockFile lockfile
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
noUmask mode (tryLockExclusive (Just mode) lockfile) >>= \case
|
tryLockExclusive (Just mode) lockfile >>= \case
|
||||||
Nothing -> noop
|
Nothing -> noop
|
||||||
Just lck -> do
|
Just lck -> do
|
||||||
forceStopSsh socketfile
|
forceStopSsh socketfile
|
||||||
|
|
|
@ -31,6 +31,7 @@ import Annex.Perms
|
||||||
import Annex.Action
|
import Annex.Action
|
||||||
import Utility.Metered
|
import Utility.Metered
|
||||||
import Utility.ThreadScheduler
|
import Utility.ThreadScheduler
|
||||||
|
import Utility.FileMode
|
||||||
import Annex.LockPool
|
import Annex.LockPool
|
||||||
import Types.Key
|
import Types.Key
|
||||||
import qualified Types.Remote as Remote
|
import qualified Types.Remote as Remote
|
||||||
|
@ -144,7 +145,7 @@ runTransfer' ignorelock t eventualbackend afile stalldetection retrydecider tran
|
||||||
else recordFailedTransfer t info
|
else recordFailedTransfer t info
|
||||||
return v
|
return v
|
||||||
|
|
||||||
prep :: RawFilePath -> Annex () -> FileMode -> Annex (Maybe LockHandle, Bool)
|
prep :: RawFilePath -> Annex () -> ModeSetter -> Annex (Maybe LockHandle, Bool)
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
prep tfile createtfile mode = catchPermissionDenied (const prepfailed) $ do
|
prep tfile createtfile mode = catchPermissionDenied (const prepfailed) $ do
|
||||||
let lck = transferLockFile tfile
|
let lck = transferLockFile tfile
|
||||||
|
|
|
@ -33,6 +33,8 @@ git-annex (10.20230408) UNRELEASED; urgency=medium
|
||||||
* Bug fix: Create .git/annex/, .git/annex/fsckdb,
|
* Bug fix: Create .git/annex/, .git/annex/fsckdb,
|
||||||
.git/annex/sentinal, .git/annex/sentinal.cache, and
|
.git/annex/sentinal, .git/annex/sentinal.cache, and
|
||||||
.git/annex/journal/* with permissions configured by core.sharedRepository.
|
.git/annex/journal/* with permissions configured by core.sharedRepository.
|
||||||
|
* Bug fix: Lock files were created with wrong modes for some combinations
|
||||||
|
of core.sharedRepository and umask.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Sat, 08 Apr 2023 13:57:18 -0400
|
-- Joey Hess <id@joeyh.name> Sat, 08 Apr 2023 13:57:18 -0400
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ runHooks r starthook stophook a = do
|
||||||
unlockFile lck
|
unlockFile lck
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
mode <- annexFileMode
|
mode <- annexFileMode
|
||||||
v <- noUmask mode $ tryLockExclusive (Just mode) lck
|
v <- tryLockExclusive (Just mode) lck
|
||||||
#else
|
#else
|
||||||
v <- liftIO $ lockExclusive lck
|
v <- liftIO $ lockExclusive lck
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- File mode utilities.
|
{- File mode utilities.
|
||||||
-
|
-
|
||||||
- Copyright 2010-2020 Joey Hess <id@joeyh.name>
|
- Copyright 2010-2023 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- License: BSD-2-clause
|
- License: BSD-2-clause
|
||||||
-}
|
-}
|
||||||
|
@ -103,16 +103,19 @@ checkMode checkfor mode = checkfor `intersectFileModes` mode == checkfor
|
||||||
isExecutable :: FileMode -> Bool
|
isExecutable :: FileMode -> Bool
|
||||||
isExecutable mode = combineModes executeModes `intersectFileModes` mode /= 0
|
isExecutable mode = combineModes executeModes `intersectFileModes` mode /= 0
|
||||||
|
|
||||||
{- Runs an action without that pesky umask influencing it, unless the
|
data ModeSetter = ModeSetter FileMode (RawFilePath -> IO ())
|
||||||
- passed FileMode is the standard one. -}
|
|
||||||
noUmask :: (MonadIO m, MonadMask m) => FileMode -> m a -> m a
|
{- Runs an action which should create the file, passing it the desired
|
||||||
#ifndef mingw32_HOST_OS
|
- initial file mode. Then runs the ModeSetter's action on the file, which
|
||||||
noUmask mode a
|
- can adjust the initial mode if umask prevented the file from being
|
||||||
| mode == stdFileMode = a
|
- created with the right mode. -}
|
||||||
| otherwise = withUmask nullFileMode a
|
applyModeSetter :: Maybe ModeSetter -> RawFilePath -> (Maybe FileMode -> IO a) -> IO a
|
||||||
#else
|
applyModeSetter (Just (ModeSetter mode modeaction)) file a = do
|
||||||
noUmask _ a = a
|
r <- a (Just mode)
|
||||||
#endif
|
void $ tryIO $ modeaction file
|
||||||
|
return r
|
||||||
|
applyModeSetter Nothing _ a =
|
||||||
|
a Nothing
|
||||||
|
|
||||||
withUmask :: (MonadIO m, MonadMask m) => FileMode -> m a -> m a
|
withUmask :: (MonadIO m, MonadMask m) => FileMode -> m a -> m a
|
||||||
#ifndef mingw32_HOST_OS
|
#ifndef mingw32_HOST_OS
|
||||||
|
@ -172,8 +175,8 @@ writeFileProtected file content = writeFileProtected' file
|
||||||
(\h -> hPutStr h content)
|
(\h -> hPutStr h content)
|
||||||
|
|
||||||
writeFileProtected' :: RawFilePath -> (Handle -> IO ()) -> IO ()
|
writeFileProtected' :: RawFilePath -> (Handle -> IO ()) -> IO ()
|
||||||
writeFileProtected' file writer = protectedOutput $
|
writeFileProtected' file writer = do
|
||||||
withFile (fromRawFilePath file) WriteMode $ \h -> do
|
h <- protectedOutput $ openFile (fromRawFilePath file) WriteMode
|
||||||
void $ tryIO $ modifyFileMode file $ removeModes otherGroupModes
|
void $ tryIO $ modifyFileMode file $ removeModes otherGroupModes
|
||||||
writer h
|
writer h
|
||||||
|
|
||||||
|
|
|
@ -83,8 +83,7 @@ trySideLock :: PidLockFile -> (SideLockHandle -> IO a) -> IO a
|
||||||
trySideLock lockfile a = do
|
trySideLock lockfile a = do
|
||||||
sidelock <- sideLockFile lockfile
|
sidelock <- sideLockFile lockfile
|
||||||
mlck <- catchDefaultIO Nothing $
|
mlck <- catchDefaultIO Nothing $
|
||||||
withUmask nullFileMode $
|
Posix.tryLockExclusive (Just modesetter) sidelock
|
||||||
Posix.tryLockExclusive (Just mode) sidelock
|
|
||||||
-- Check the lock we just took, in case we opened a side lock file
|
-- Check the lock we just took, in case we opened a side lock file
|
||||||
-- belonging to another process that will have since deleted it.
|
-- belonging to another process that will have since deleted it.
|
||||||
case mlck of
|
case mlck of
|
||||||
|
@ -100,6 +99,7 @@ trySideLock lockfile a = do
|
||||||
-- delete another user's lock file there, so could not
|
-- delete another user's lock file there, so could not
|
||||||
-- delete a stale lock.
|
-- delete a stale lock.
|
||||||
mode = combineModes (readModes ++ writeModes)
|
mode = combineModes (readModes ++ writeModes)
|
||||||
|
modesetter = ModeSetter mode (\f -> modifyFileMode f (const mode))
|
||||||
|
|
||||||
dropSideLock :: SideLockHandle -> IO ()
|
dropSideLock :: SideLockHandle -> IO ()
|
||||||
dropSideLock Nothing = return ()
|
dropSideLock Nothing = return ()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- Posix lock files
|
{- Posix lock files
|
||||||
-
|
-
|
||||||
- Copyright 2014 Joey Hess <id@joeyh.name>
|
- Copyright 2014-2023 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- License: BSD-2-clause
|
- License: BSD-2-clause
|
||||||
-}
|
-}
|
||||||
|
@ -22,6 +22,7 @@ module Utility.LockFile.Posix (
|
||||||
|
|
||||||
import Utility.Exception
|
import Utility.Exception
|
||||||
import Utility.Applicative
|
import Utility.Applicative
|
||||||
|
import Utility.FileMode
|
||||||
import Utility.LockFile.LockStatus
|
import Utility.LockFile.LockStatus
|
||||||
|
|
||||||
import System.IO
|
import System.IO
|
||||||
|
@ -36,31 +37,31 @@ type LockFile = RawFilePath
|
||||||
newtype LockHandle = LockHandle Fd
|
newtype LockHandle = LockHandle Fd
|
||||||
|
|
||||||
-- Takes a shared lock, blocking until the lock is available.
|
-- Takes a shared lock, blocking until the lock is available.
|
||||||
lockShared :: Maybe FileMode -> LockFile -> IO LockHandle
|
lockShared :: Maybe ModeSetter -> LockFile -> IO LockHandle
|
||||||
lockShared = lock ReadLock
|
lockShared = lock ReadLock
|
||||||
|
|
||||||
-- Takes an exclusive lock, blocking until the lock is available.
|
-- Takes an exclusive lock, blocking until the lock is available.
|
||||||
lockExclusive :: Maybe FileMode -> LockFile -> IO LockHandle
|
lockExclusive :: Maybe ModeSetter -> LockFile -> IO LockHandle
|
||||||
lockExclusive = lock WriteLock
|
lockExclusive = lock WriteLock
|
||||||
|
|
||||||
-- Tries to take a shared lock, but does not block.
|
-- Tries to take a shared lock, but does not block.
|
||||||
tryLockShared :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
|
tryLockShared :: Maybe ModeSetter -> LockFile -> IO (Maybe LockHandle)
|
||||||
tryLockShared = tryLock ReadLock
|
tryLockShared = tryLock ReadLock
|
||||||
|
|
||||||
-- Tries to take an exclusive lock, but does not block.
|
-- Tries to take an exclusive lock, but does not block.
|
||||||
tryLockExclusive :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
|
tryLockExclusive :: Maybe ModeSetter -> LockFile -> IO (Maybe LockHandle)
|
||||||
tryLockExclusive = tryLock WriteLock
|
tryLockExclusive = tryLock WriteLock
|
||||||
|
|
||||||
-- Setting the FileMode allows creation of a new lock file.
|
-- Setting the FileMode allows creation of a new lock file.
|
||||||
-- If it's Nothing then this only succeeds when the lock file already exists.
|
-- If it's Nothing then this only succeeds when the lock file already exists.
|
||||||
lock :: LockRequest -> Maybe FileMode -> LockFile -> IO LockHandle
|
lock :: LockRequest -> Maybe ModeSetter -> LockFile -> IO LockHandle
|
||||||
lock lockreq mode lockfile = do
|
lock lockreq mode lockfile = do
|
||||||
l <- openLockFile lockreq mode lockfile
|
l <- openLockFile lockreq mode lockfile
|
||||||
waitToSetLock l (lockreq, AbsoluteSeek, 0, 0)
|
waitToSetLock l (lockreq, AbsoluteSeek, 0, 0)
|
||||||
return (LockHandle l)
|
return (LockHandle l)
|
||||||
|
|
||||||
-- Tries to take an lock, but does not block.
|
-- Tries to take an lock, but does not block.
|
||||||
tryLock :: LockRequest -> Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
|
tryLock :: LockRequest -> Maybe ModeSetter -> LockFile -> IO (Maybe LockHandle)
|
||||||
tryLock lockreq mode lockfile = uninterruptibleMask_ $ do
|
tryLock lockreq mode lockfile = uninterruptibleMask_ $ do
|
||||||
l <- openLockFile lockreq mode lockfile
|
l <- openLockFile lockreq mode lockfile
|
||||||
v <- tryIO $ setLock l (lockreq, AbsoluteSeek, 0, 0)
|
v <- tryIO $ setLock l (lockreq, AbsoluteSeek, 0, 0)
|
||||||
|
@ -71,9 +72,10 @@ tryLock lockreq mode lockfile = uninterruptibleMask_ $ do
|
||||||
Right _ -> return $ Just $ LockHandle l
|
Right _ -> return $ Just $ LockHandle l
|
||||||
|
|
||||||
-- Close on exec flag is set so child processes do not inherit the lock.
|
-- Close on exec flag is set so child processes do not inherit the lock.
|
||||||
openLockFile :: LockRequest -> Maybe FileMode -> LockFile -> IO Fd
|
openLockFile :: LockRequest -> Maybe ModeSetter -> LockFile -> IO Fd
|
||||||
openLockFile lockreq filemode lockfile = do
|
openLockFile lockreq filemode lockfile = do
|
||||||
l <- openFd lockfile openfor filemode defaultFileFlags
|
l <- applyModeSetter filemode lockfile $ \filemode' ->
|
||||||
|
openFd lockfile openfor filemode' defaultFileFlags
|
||||||
setFdOption l CloseOnExec True
|
setFdOption l CloseOnExec True
|
||||||
return l
|
return l
|
||||||
where
|
where
|
||||||
|
|
|
@ -24,6 +24,7 @@ import Utility.LockFile.LockStatus
|
||||||
import qualified Utility.LockPool.STM as P
|
import qualified Utility.LockPool.STM as P
|
||||||
import Utility.LockPool.STM (LockFile, LockMode(..))
|
import Utility.LockPool.STM (LockFile, LockMode(..))
|
||||||
import Utility.LockPool.LockHandle
|
import Utility.LockPool.LockHandle
|
||||||
|
import Utility.FileMode
|
||||||
|
|
||||||
import System.IO
|
import System.IO
|
||||||
import System.Posix
|
import System.Posix
|
||||||
|
@ -32,25 +33,25 @@ import Control.Applicative
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
-- Takes a shared lock, blocking until the lock is available.
|
-- Takes a shared lock, blocking until the lock is available.
|
||||||
lockShared :: Maybe FileMode -> LockFile -> IO LockHandle
|
lockShared :: Maybe ModeSetter -> LockFile -> IO LockHandle
|
||||||
lockShared mode file = fst <$> makeLockHandle P.lockPool file
|
lockShared mode file = fst <$> makeLockHandle P.lockPool file
|
||||||
(\p f -> P.waitTakeLock p f LockShared)
|
(\p f -> P.waitTakeLock p f LockShared)
|
||||||
(\f _ -> mk <$> F.lockShared mode f)
|
(\f _ -> mk <$> F.lockShared mode f)
|
||||||
|
|
||||||
-- Takes an exclusive lock, blocking until the lock is available.
|
-- Takes an exclusive lock, blocking until the lock is available.
|
||||||
lockExclusive :: Maybe FileMode -> LockFile -> IO LockHandle
|
lockExclusive :: Maybe ModeSetter -> LockFile -> IO LockHandle
|
||||||
lockExclusive mode file = fst <$> makeLockHandle P.lockPool file
|
lockExclusive mode file = fst <$> makeLockHandle P.lockPool file
|
||||||
(\p f -> P.waitTakeLock p f LockExclusive)
|
(\p f -> P.waitTakeLock p f LockExclusive)
|
||||||
(\f _ -> mk <$> F.lockExclusive mode f)
|
(\f _ -> mk <$> F.lockExclusive mode f)
|
||||||
|
|
||||||
-- Tries to take a shared lock, but does not block.
|
-- Tries to take a shared lock, but does not block.
|
||||||
tryLockShared :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
|
tryLockShared :: Maybe ModeSetter -> LockFile -> IO (Maybe LockHandle)
|
||||||
tryLockShared mode file = fmap fst <$> tryMakeLockHandle P.lockPool file
|
tryLockShared mode file = fmap fst <$> tryMakeLockHandle P.lockPool file
|
||||||
(\p f -> P.tryTakeLock p f LockShared)
|
(\p f -> P.tryTakeLock p f LockShared)
|
||||||
(\f _ -> fmap mk <$> F.tryLockShared mode f)
|
(\f _ -> fmap mk <$> F.tryLockShared mode f)
|
||||||
|
|
||||||
-- Tries to take an exclusive lock, but does not block.
|
-- Tries to take an exclusive lock, but does not block.
|
||||||
tryLockExclusive :: Maybe FileMode -> LockFile -> IO (Maybe LockHandle)
|
tryLockExclusive :: Maybe ModeSetter -> LockFile -> IO (Maybe LockHandle)
|
||||||
tryLockExclusive mode file = fmap fst <$> tryMakeLockHandle P.lockPool file
|
tryLockExclusive mode file = fmap fst <$> tryMakeLockHandle P.lockPool file
|
||||||
(\p f -> P.tryTakeLock p f LockExclusive)
|
(\p f -> P.tryTakeLock p f LockExclusive)
|
||||||
(\f _ -> fmap mk <$> F.tryLockExclusive mode f)
|
(\f _ -> fmap mk <$> F.tryLockExclusive mode f)
|
||||||
|
|
|
@ -2,13 +2,13 @@ With core.sharedRepository=0666, some lock files get created mode 644
|
||||||
(with umask 0022).
|
(with umask 0022).
|
||||||
|
|
||||||
With core.sharedRepository=group, some lock files get created mode 660,
|
With core.sharedRepository=group, some lock files get created mode 660,
|
||||||
rather than 644 (with umask 0022).
|
rather than 664 (with umask 0022).
|
||||||
|
|
||||||
Root of the problem is uses of annexFileMode.
|
Root of the problem is uses of annexFileMode.
|
||||||
|
|
||||||
Some callers use noUmask with it, which works in cases other than these (at
|
Some callers use noUmask with it, which works in cases other than these (at
|
||||||
least with umask 0022). But in the core.sharedRepository=group case, the
|
least with umask 0022). But in the core.sharedRepository=group case, the
|
||||||
umask is cleared by noUmask, which is why the g+r bit is not set.
|
umask is cleared by noUmask, which is why the o+r bit is not set.
|
||||||
|
|
||||||
Some callers don't use noUmask with it, and when
|
Some callers don't use noUmask with it, and when
|
||||||
core.sharedRepository=0666, that results in the umask being applied
|
core.sharedRepository=0666, that results in the umask being applied
|
||||||
|
@ -20,3 +20,5 @@ Fix will probably involve getting rid of annexFileMode, and noUmask, and
|
||||||
creating the lock file with default umask, then fixing up the mode if necessary,
|
creating the lock file with default umask, then fixing up the mode if necessary,
|
||||||
before using it. Ie, the same pattern used everywhere else in git-annex.
|
before using it. Ie, the same pattern used everywhere else in git-annex.
|
||||||
--[[Joey]]
|
--[[Joey]]
|
||||||
|
|
||||||
|
> [[fixed|done]] --[[Joey]]
|
||||||
|
|
Loading…
Reference in a new issue