2012-04-21 20:59:49 +00:00
|
|
|
{- git-annex file permissions
|
|
|
|
-
|
|
|
|
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Annex.Perms (
|
2013-11-18 22:05:37 +00:00
|
|
|
setAnnexFilePerm,
|
|
|
|
setAnnexDirPerm,
|
2012-04-21 20:59:49 +00:00
|
|
|
annexFileMode,
|
|
|
|
createAnnexDirectory,
|
|
|
|
noUmask,
|
2013-01-26 09:09:15 +00:00
|
|
|
createContentDir,
|
|
|
|
freezeContentDir,
|
2013-04-30 23:09:36 +00:00
|
|
|
thawContentDir,
|
2013-11-15 18:52:03 +00:00
|
|
|
modifyContent,
|
2012-04-21 20:59:49 +00:00
|
|
|
) where
|
|
|
|
|
|
|
|
import Common.Annex
|
|
|
|
import Utility.FileMode
|
|
|
|
import Git.SharedRepository
|
2012-04-21 23:42:49 +00:00
|
|
|
import qualified Annex
|
2013-02-14 18:10:36 +00:00
|
|
|
import Config
|
2012-04-21 20:59:49 +00:00
|
|
|
|
|
|
|
import System.Posix.Types
|
|
|
|
|
2012-04-21 23:42:49 +00:00
|
|
|
withShared :: (SharedRepository -> Annex a) -> Annex a
|
|
|
|
withShared a = maybe startup a =<< Annex.getState Annex.shared
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
|
|
|
startup = do
|
|
|
|
shared <- fromRepo getSharedRepository
|
|
|
|
Annex.changeState $ \s -> s { Annex.shared = Just shared }
|
|
|
|
a shared
|
2012-04-21 23:42:49 +00:00
|
|
|
|
2013-11-18 22:05:37 +00:00
|
|
|
setAnnexFilePerm :: FilePath -> Annex ()
|
|
|
|
setAnnexFilePerm = setAnnexPerm False
|
|
|
|
|
|
|
|
setAnnexDirPerm :: FilePath -> Annex ()
|
|
|
|
setAnnexDirPerm = setAnnexPerm True
|
|
|
|
|
2012-04-21 20:59:49 +00:00
|
|
|
{- Sets appropriate file mode for a file or directory in the annex,
|
|
|
|
- other than the content files and content directory. Normally,
|
|
|
|
- use the default mode, but with core.sharedRepository set,
|
|
|
|
- allow the group to write, etc. -}
|
2013-11-18 22:05:37 +00:00
|
|
|
setAnnexPerm :: Bool -> FilePath -> Annex ()
|
|
|
|
setAnnexPerm isdir file = unlessM crippledFileSystem $
|
2013-02-14 18:10:36 +00:00
|
|
|
withShared $ liftIO . go
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
2013-11-18 22:05:37 +00:00
|
|
|
go GroupShared = modifyFileMode file $ addModes $
|
|
|
|
groupSharedModes ++
|
|
|
|
if isdir then [ ownerExecuteMode, groupExecuteMode ] else []
|
2012-12-13 04:24:19 +00:00
|
|
|
go AllShared = modifyFileMode file $ addModes $
|
2013-11-18 22:05:37 +00:00
|
|
|
readModes ++
|
|
|
|
[ ownerWriteMode, groupWriteMode ] ++
|
|
|
|
if isdir then executeModes else []
|
2012-12-13 04:24:19 +00:00
|
|
|
go _ = noop
|
2012-04-21 20:59:49 +00:00
|
|
|
|
|
|
|
{- Gets the appropriate mode to use for creating a file in the annex
|
|
|
|
- (other than content files, which are locked down more). -}
|
|
|
|
annexFileMode :: Annex FileMode
|
2012-04-21 23:42:49 +00:00
|
|
|
annexFileMode = withShared $ return . go
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
|
|
|
go GroupShared = sharedmode
|
|
|
|
go AllShared = combineModes (sharedmode:readModes)
|
|
|
|
go _ = stdFileMode
|
2013-11-18 22:05:37 +00:00
|
|
|
sharedmode = combineModes groupSharedModes
|
2012-04-21 20:59:49 +00:00
|
|
|
|
|
|
|
{- Creates a directory inside the gitAnnexDir, including any parent
|
|
|
|
- directories. Makes directories with appropriate permissions. -}
|
|
|
|
createAnnexDirectory :: FilePath -> Annex ()
|
|
|
|
createAnnexDirectory dir = traverse dir [] =<< top
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
2015-01-09 17:11:56 +00:00
|
|
|
top = parentDir <$> fromRepo gitAnnexDir
|
2012-12-13 04:24:19 +00:00
|
|
|
traverse d below stop
|
|
|
|
| d `equalFilePath` stop = done
|
|
|
|
| otherwise = ifM (liftIO $ doesDirectoryExist d)
|
|
|
|
( done
|
2015-01-09 17:11:56 +00:00
|
|
|
, traverse (parentDir d) (d:below) stop
|
2012-12-13 04:24:19 +00:00
|
|
|
)
|
|
|
|
where
|
|
|
|
done = forM_ below $ \p -> do
|
2013-02-24 21:40:14 +00:00
|
|
|
liftIO $ createDirectoryIfMissing True p
|
2013-11-18 22:05:37 +00:00
|
|
|
setAnnexDirPerm p
|
2013-01-26 09:09:15 +00:00
|
|
|
|
|
|
|
{- Blocks writing to the directory an annexed file is in, to prevent the
|
|
|
|
- file accidentially being deleted. However, if core.sharedRepository
|
|
|
|
- is set, this is not done, since the group must be allowed to delete the
|
|
|
|
- file.
|
|
|
|
-}
|
|
|
|
freezeContentDir :: FilePath -> Annex ()
|
2013-02-14 18:10:36 +00:00
|
|
|
freezeContentDir file = unlessM crippledFileSystem $
|
|
|
|
liftIO . go =<< fromRepo getSharedRepository
|
2013-01-26 09:09:15 +00:00
|
|
|
where
|
2015-01-09 17:11:56 +00:00
|
|
|
dir = parentDir file
|
2013-01-26 09:09:15 +00:00
|
|
|
go GroupShared = groupWriteRead dir
|
|
|
|
go AllShared = groupWriteRead dir
|
|
|
|
go _ = preventWrite dir
|
|
|
|
|
2013-04-30 23:09:36 +00:00
|
|
|
thawContentDir :: FilePath -> Annex ()
|
|
|
|
thawContentDir file = unlessM crippledFileSystem $
|
2015-01-09 17:11:56 +00:00
|
|
|
liftIO $ allowWrite $ parentDir file
|
2013-04-30 23:09:36 +00:00
|
|
|
|
2013-01-26 09:09:15 +00:00
|
|
|
{- Makes the directory tree to store an annexed file's content,
|
|
|
|
- with appropriate permissions on each level. -}
|
|
|
|
createContentDir :: FilePath -> Annex ()
|
|
|
|
createContentDir dest = do
|
|
|
|
unlessM (liftIO $ doesDirectoryExist dir) $
|
|
|
|
createAnnexDirectory dir
|
|
|
|
-- might have already existed with restricted perms
|
2013-02-14 18:10:36 +00:00
|
|
|
unlessM crippledFileSystem $
|
|
|
|
liftIO $ allowWrite dir
|
2013-01-26 09:09:15 +00:00
|
|
|
where
|
2015-01-09 17:11:56 +00:00
|
|
|
dir = parentDir dest
|
2013-11-15 18:52:03 +00:00
|
|
|
|
|
|
|
{- Creates the content directory for a file if it doesn't already exist,
|
|
|
|
- or thaws it if it does, then runs an action to modify the file, and
|
|
|
|
- finally, freezes the content directory. -}
|
|
|
|
modifyContent :: FilePath -> Annex a -> Annex a
|
|
|
|
modifyContent f a = do
|
|
|
|
createContentDir f -- also thaws it
|
unify exception handling into Utility.Exception
Removed old extensible-exceptions, only needed for very old ghc.
Made webdav use Utility.Exception, to work after some changes in DAV's
exception handling.
Removed Annex.Exception. Mostly this was trivial, but note that
tryAnnex is replaced with tryNonAsync and catchAnnex replaced with
catchNonAsync. In theory that could be a behavior change, since the former
caught all exceptions, and the latter don't catch async exceptions.
However, in practice, nothing in the Annex monad uses async exceptions.
Grepping for throwTo and killThread only find stuff in the assistant,
which does not seem related.
Command.Add.undo is changed to accept a SomeException, and things
that use it for rollback now catch non-async exceptions, rather than
only IOExceptions.
2014-08-08 01:55:44 +00:00
|
|
|
v <- tryNonAsync a
|
2013-11-15 18:52:03 +00:00
|
|
|
freezeContentDir f
|
unify exception handling into Utility.Exception
Removed old extensible-exceptions, only needed for very old ghc.
Made webdav use Utility.Exception, to work after some changes in DAV's
exception handling.
Removed Annex.Exception. Mostly this was trivial, but note that
tryAnnex is replaced with tryNonAsync and catchAnnex replaced with
catchNonAsync. In theory that could be a behavior change, since the former
caught all exceptions, and the latter don't catch async exceptions.
However, in practice, nothing in the Annex monad uses async exceptions.
Grepping for throwTo and killThread only find stuff in the assistant,
which does not seem related.
Command.Add.undo is changed to accept a SomeException, and things
that use it for rollback now catch non-async exceptions, rather than
only IOExceptions.
2014-08-08 01:55:44 +00:00
|
|
|
either throwM return v
|