ignore write bits being set when there is a freeze hook
When annex.freezecontent-command is set, and the filesystem does not support removing write bits, avoid treating it as a crippled filesystem. The hook may be enough to prevent writing on its own, and some filesystems ignore attempts to remove write bits. Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
parent
4144f73c18
commit
28bc5ce232
6 changed files with 46 additions and 18 deletions
|
@ -251,6 +251,7 @@ probeCrippledFileSystem = withEventuallyCleanedOtherTmp $ \tmp -> do
|
|||
(r, warnings) <- probeCrippledFileSystem' tmp
|
||||
(Just (freezeContent' UnShared))
|
||||
(Just (thawContent' UnShared))
|
||||
=<< hasFreezeHook
|
||||
mapM_ warning warnings
|
||||
return r
|
||||
|
||||
|
@ -259,11 +260,12 @@ probeCrippledFileSystem'
|
|||
=> RawFilePath
|
||||
-> Maybe (RawFilePath -> m ())
|
||||
-> Maybe (RawFilePath -> m ())
|
||||
-> Bool
|
||||
-> m (Bool, [String])
|
||||
#ifdef mingw32_HOST_OS
|
||||
probeCrippledFileSystem' _ _ _ = return (True, [])
|
||||
probeCrippledFileSystem' _ _ _ _ = return (True, [])
|
||||
#else
|
||||
probeCrippledFileSystem' tmp freezecontent thawcontent = do
|
||||
probeCrippledFileSystem' tmp freezecontent thawcontent hasfreezehook = do
|
||||
let f = tmp P.</> "gaprobe"
|
||||
let f' = fromRawFilePath f
|
||||
liftIO $ writeFile f' ""
|
||||
|
@ -282,7 +284,7 @@ probeCrippledFileSystem' tmp freezecontent thawcontent = do
|
|||
-- running as root). But some crippled
|
||||
-- filesystems ignore write bit removals or ignore
|
||||
-- permissions entirely.
|
||||
ifM ((== Just False) <$> liftIO (checkContentWritePerm' UnShared (toRawFilePath f) Nothing))
|
||||
ifM ((== Just False) <$> liftIO (checkContentWritePerm' UnShared (toRawFilePath f) Nothing hasfreezehook))
|
||||
( return (True, ["Filesystem does not allow removing write bit from files."])
|
||||
, liftIO $ ifM ((== 0) <$> getRealUserID)
|
||||
( return (False, [])
|
||||
|
|
|
@ -26,6 +26,7 @@ module Annex.Perms (
|
|||
thawContentDir,
|
||||
modifyContent,
|
||||
withShared,
|
||||
hasFreezeHook,
|
||||
) where
|
||||
|
||||
import Annex.Common
|
||||
|
@ -183,26 +184,35 @@ freezeContent'' sr file rv = do
|
|||
- permissions of a file owned by another user. So if the permissions seem
|
||||
- wrong, but the repository is shared, returns Nothing. If the permissions
|
||||
- are wrong otherwise, returns Just False.
|
||||
-
|
||||
- When there is a freeze hook, it may prevent write in some way other than
|
||||
- permissions. One use of a freeze hook is when the filesystem does not
|
||||
- support removing write permissions, so when there is such a hook
|
||||
- write permissions are ignored.
|
||||
-}
|
||||
checkContentWritePerm :: RawFilePath -> Annex (Maybe Bool)
|
||||
checkContentWritePerm file = ifM crippledFileSystem
|
||||
( return (Just True)
|
||||
, do
|
||||
rv <- getVersion
|
||||
withShared (\sr -> liftIO (checkContentWritePerm' sr file rv))
|
||||
hasfreezehook <- hasFreezeHook
|
||||
withShared $ \sr -> liftIO $
|
||||
checkContentWritePerm' sr file rv hasfreezehook
|
||||
)
|
||||
|
||||
checkContentWritePerm' :: SharedRepository -> RawFilePath -> Maybe RepoVersion -> IO (Maybe Bool)
|
||||
checkContentWritePerm' sr file rv = case sr of
|
||||
GroupShared
|
||||
| versionNeedsWritableContentFiles rv -> want sharedret
|
||||
(includemodes [ownerWriteMode, groupWriteMode])
|
||||
| otherwise -> want sharedret (excludemodes writeModes)
|
||||
AllShared
|
||||
| versionNeedsWritableContentFiles rv ->
|
||||
want sharedret (includemodes writeModes)
|
||||
| otherwise -> want sharedret (excludemodes writeModes)
|
||||
_ -> want Just (excludemodes writeModes)
|
||||
checkContentWritePerm' :: SharedRepository -> RawFilePath -> Maybe RepoVersion -> Bool -> IO (Maybe Bool)
|
||||
checkContentWritePerm' sr file rv hasfreezehook
|
||||
| hasfreezehook = return (Just True)
|
||||
| otherwise = case sr of
|
||||
GroupShared
|
||||
| versionNeedsWritableContentFiles rv -> want sharedret
|
||||
(includemodes [ownerWriteMode, groupWriteMode])
|
||||
| otherwise -> want sharedret (excludemodes writeModes)
|
||||
AllShared
|
||||
| versionNeedsWritableContentFiles rv ->
|
||||
want sharedret (includemodes writeModes)
|
||||
| otherwise -> want sharedret (excludemodes writeModes)
|
||||
_ -> want Just (excludemodes writeModes)
|
||||
where
|
||||
want mk f = catchMaybeIO (fileMode <$> R.getFileStatus file)
|
||||
>>= return . \case
|
||||
|
@ -280,6 +290,9 @@ modifyContent f a = do
|
|||
freezeContentDir f
|
||||
either throwM return v
|
||||
|
||||
hasFreezeHook :: Annex Bool
|
||||
hasFreezeHook = isJust . annexFreezeContentCommand <$> Annex.getGitConfig
|
||||
|
||||
freezeHook :: RawFilePath -> Annex ()
|
||||
freezeHook p = maybe noop go =<< annexFreezeContentCommand <$> Annex.getGitConfig
|
||||
where
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue