defer write permissions checking in import until after copy to repo

This should complete the fix started in
6329997ac4, fixing the actual cause of the
test suite failure this time.

Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
Joey Hess 2021-09-02 13:45:21 -04:00
parent 7b26222cbe
commit ec12537774
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
8 changed files with 64 additions and 19 deletions

View file

@ -9,6 +9,7 @@ module Annex.Ingest (
LockedDown(..), LockedDown(..),
LockDownConfig(..), LockDownConfig(..),
lockDown, lockDown,
checkLockedDownWritePerms,
ingestAdd, ingestAdd,
ingestAdd', ingestAdd',
ingest, ingest,
@ -61,7 +62,9 @@ data LockDownConfig = LockDownConfig
{ lockingFile :: Bool { lockingFile :: Bool
-- ^ write bit removed during lock down -- ^ write bit removed during lock down
, hardlinkFileTmpDir :: Maybe RawFilePath , hardlinkFileTmpDir :: Maybe RawFilePath
-- ^ hard link to temp directory -- ^ hard link to temp directorya
, checkWritePerms :: Bool
-- ^ check that write perms are successfully removed
} }
deriving (Show) deriving (Show)
@ -79,7 +82,7 @@ data LockDownConfig = LockDownConfig
- Lockdown can fail if a file gets deleted, or if it's unable to remove - Lockdown can fail if a file gets deleted, or if it's unable to remove
- write permissions, and Nothing will be returned. - write permissions, and Nothing will be returned.
-} -}
lockDown :: LockDownConfig -> FilePath -> Annex (Maybe LockedDown) lockDown :: LockDownConfig-> FilePath -> Annex (Maybe LockedDown)
lockDown cfg file = either lockDown cfg file = either
(\e -> warning (show e) >> return Nothing) (\e -> warning (show e) >> return Nothing)
(return . Just) (return . Just)
@ -128,13 +131,17 @@ lockDown' cfg file = tryNonAsync $ ifM crippledFileSystem
setperms = when (lockingFile cfg) $ do setperms = when (lockingFile cfg) $ do
freezeContent file' freezeContent file'
checkContentWritePerm file' >>= \case when (checkWritePerms cfg) $
Just False -> giveup $ unwords maybe noop giveup =<< checkLockedDownWritePerms file' file'
[ "Unable to remove all write permissions from"
, file checkLockedDownWritePerms :: RawFilePath -> RawFilePath -> Annex (Maybe String)
, "-- perhaps it has an xattr or ACL set." checkLockedDownWritePerms file displayfile = checkContentWritePerm file >>= return . \case
] Just False -> Just $ unwords
_ -> return () [ "Unable to remove all write permissions from"
, fromRawFilePath displayfile
, "-- perhaps it has an xattr or ACL set."
]
_ -> Nothing
{- Ingests a locked down file into the annex. Updates the work tree and {- Ingests a locked down file into the annex. Updates the work tree and
- index. -} - index. -}

View file

@ -265,6 +265,7 @@ handleAdds lockdowndir havelsof largefilematcher delayadd cs = returnWhen (null
let lockdownconfig = LockDownConfig let lockdownconfig = LockDownConfig
{ lockingFile = False { lockingFile = False
, hardlinkFileTmpDir = Just (toRawFilePath lockdowndir) , hardlinkFileTmpDir = Just (toRawFilePath lockdowndir)
, checkWritePerms = True
} }
(postponed, toadd) <- partitionEithers (postponed, toadd) <- partitionEithers
<$> safeToAdd lockdowndir lockdownconfig havelsof delayadd pending inprocess <$> safeToAdd lockdowndir lockdownconfig havelsof delayadd pending inprocess
@ -310,6 +311,7 @@ handleAdds lockdowndir havelsof largefilematcher delayadd cs = returnWhen (null
let cfg = LockDownConfig let cfg = LockDownConfig
{ lockingFile = False { lockingFile = False
, hardlinkFileTmpDir = Just (toRawFilePath lockdowndir) , hardlinkFileTmpDir = Just (toRawFilePath lockdowndir)
, checkWritePerms = True
} }
if M.null m if M.null m
then forM toadd (addannexed' cfg) then forM toadd (addannexed' cfg)

View file

@ -22,8 +22,9 @@ git-annex (8.20210804) UNRELEASED; urgency=medium
* Run cp -a with --no-preserve=xattr, to avoid problems with copied * Run cp -a with --no-preserve=xattr, to avoid problems with copied
xattrs, including them breaking permissions setting on some NFS xattrs, including them breaking permissions setting on some NFS
servers. servers.
* add: Detect when xattrs or perhaps ACLs prevent locking down * add, import: Detect when xattrs or perhaps ACLs prevent removing
a file's content, and fail with an informative message. write permissions from an annexed file, and fail with an informative
message.
* Fix support for readonly git remotes. * Fix support for readonly git remotes.
(Reversion in version 8.20210621) (Reversion in version 8.20210621)
* When downloading urls fail, explain which urls failed for which * When downloading urls fail, explain which urls failed for which

View file

@ -188,6 +188,7 @@ perform o file addunlockedmatcher = withOtherTmp $ \tmpdir -> do
let cfg = LockDownConfig let cfg = LockDownConfig
{ lockingFile = lockingfile { lockingFile = lockingfile
, hardlinkFileTmpDir = Just tmpdir , hardlinkFileTmpDir = Just tmpdir
, checkWritePerms = True
} }
ld <- lockDown cfg (fromRawFilePath file) ld <- lockDown cfg (fromRawFilePath file)
let sizer = keySource <$> ld let sizer = keySource <$> ld

View file

@ -1,6 +1,6 @@
{- git-annex command {- git-annex command
- -
- Copyright 2012-2020 Joey Hess <id@joeyh.name> - Copyright 2012-2021 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -200,13 +200,31 @@ startLocal o addunlockedmatcher largematcher mode (srcfile, destfile) =
-- Move or copy the src file to the dest file. -- Move or copy the src file to the dest file.
-- The dest file is what will be ingested. -- The dest file is what will be ingested.
createWorkTreeDirectory (parentDir destfile) createWorkTreeDirectory (parentDir destfile)
liftIO $ if mode == Duplicate || mode == SkipDuplicates unwind <- liftIO $ if mode == Duplicate || mode == SkipDuplicates
then void $ copyFileExternal CopyAllMetaData then do
(fromRawFilePath srcfile) void $ copyFileExternal CopyAllMetaData
(fromRawFilePath destfile) (fromRawFilePath srcfile)
else moveFile (fromRawFilePath destfile)
(fromRawFilePath srcfile) return $ removeWhenExistsWith R.removeLink destfile
(fromRawFilePath destfile) else do
moveFile
(fromRawFilePath srcfile)
(fromRawFilePath destfile)
return $ moveFile
(fromRawFilePath destfile)
(fromRawFilePath srcfile)
-- Make sure that the dest file has its write permissions
-- removed; the src file normally already did, but may
-- have imported it from a filesystem that does not allow
-- removing write permissions, to a repo on a filesystem
-- that does.
when (lockingFile (lockDownConfig ld)) $ do
freezeContent destfile
checkLockedDownWritePerms destfile srcfile >>= \case
Just err -> do
liftIO unwind
giveup err
Nothing -> noop
-- Get the inode cache of the dest file. It should be -- Get the inode cache of the dest file. It should be
-- weakly the same as the originally locked down file's -- weakly the same as the originally locked down file's
-- inode cache. (Since the file may have been copied, -- inode cache. (Since the file may have been copied,
@ -249,6 +267,12 @@ startLocal o addunlockedmatcher largematcher mode (srcfile, destfile) =
let cfg = LockDownConfig let cfg = LockDownConfig
{ lockingFile = lockingfile { lockingFile = lockingfile
, hardlinkFileTmpDir = Nothing , hardlinkFileTmpDir = Nothing
-- The write perms of the file may not be able to be
-- removed, if it's being imported from a crippled
-- filesystem. So lockDown is asked to not check
-- the write perms. They will be checked later, after
-- the file gets copied into the repository.
, checkWritePerms = False
} }
v <- lockDown cfg (fromRawFilePath srcfile) v <- lockDown cfg (fromRawFilePath srcfile)
case v of case v of

View file

@ -160,6 +160,7 @@ clean file = do
cfg = LockDownConfig cfg = LockDownConfig
{ lockingFile = False { lockingFile = False
, hardlinkFileTmpDir = Nothing , hardlinkFileTmpDir = Nothing
, checkWritePerms = True
} }
-- git diff can run the clean filter on files outside the -- git diff can run the clean filter on files outside the

View file

@ -38,3 +38,5 @@ Both look like
[[!meta author=yoh]] [[!meta author=yoh]]
[[!tag projects/datalad]] [[!tag projects/datalad]]
> [[fixed|done]] (provisionally, waiting on test run) --[[Joey]]

View file

@ -0,0 +1,7 @@
[[!comment format=mdwn
username="joey"
subject="""comment 5"""
date="2021-09-02T17:39:20Z"
content="""
Ok, fixed some more, hopefully all the way this time..
"""]]