diff options
-rw-r--r-- | Backend/SHA1.hs | 3 | ||||
-rw-r--r-- | Backend/URL.hs | 2 | ||||
-rw-r--r-- | Command/SetKey.hs | 3 | ||||
-rw-r--r-- | CopyFile.hs | 10 | ||||
-rw-r--r-- | Remotes.hs | 2 | ||||
-rw-r--r-- | RsyncFile.hs | 5 | ||||
-rw-r--r-- | Utility.hs | 8 | ||||
-rw-r--r-- | debian/changelog | 3 | ||||
-rw-r--r-- | doc/bugs/error_with_file_names_starting_with_dash.mdwn | 3 |
9 files changed, 29 insertions, 10 deletions
diff --git a/Backend/SHA1.hs b/Backend/SHA1.hs index 9636787f0..e1830bc13 100644 --- a/Backend/SHA1.hs +++ b/Backend/SHA1.hs @@ -20,6 +20,7 @@ import qualified Annex import Locations import Content import Types +import Utility backend :: Backend Annex backend = Backend.File.backend { @@ -31,7 +32,7 @@ backend = Backend.File.backend { sha1 :: FilePath -> Annex String sha1 file = do showNote "checksum..." - liftIO $ pOpen ReadFromPipe "sha1sum" [file] $ \h -> do + liftIO $ pOpen ReadFromPipe "sha1sum" [utilityEscape file] $ \h -> do line <- hGetLine h let bits = split " " line if null bits diff --git a/Backend/URL.hs b/Backend/URL.hs index 38954e5a3..15cc88d64 100644 --- a/Backend/URL.hs +++ b/Backend/URL.hs @@ -51,6 +51,6 @@ downloadUrl :: Key -> FilePath -> Annex Bool downloadUrl key file = do showNote "downloading" showProgress -- make way for curl progress bar - liftIO $ boolSystem "curl" ["-#", "-o", file, url] + liftIO $ boolSystem "curl" ["-#", "-o", utilityEscape file, url] where url = join ":" $ drop 1 $ split ":" $ show key diff --git a/Command/SetKey.hs b/Command/SetKey.hs index 388392cd6..025fb74d6 100644 --- a/Command/SetKey.hs +++ b/Command/SetKey.hs @@ -35,7 +35,8 @@ perform file = do -- rather than simply calling moveToObjectDir ok <- getViaTmp key $ \dest -> do if dest /= file - then liftIO $ boolSystem "mv" [file, dest] + then liftIO $ + boolSystem "mv" [utilityEscape file, utilityEscape dest] else return True if ok then return $ Just $ cleanup diff --git a/CopyFile.hs b/CopyFile.hs index e913aa070..73d911a29 100644 --- a/CopyFile.hs +++ b/CopyFile.hs @@ -23,9 +23,11 @@ copyFile src dest = do boolSystem "cp" opts where opts = if SysConfig.cp_reflink_auto - then ["--reflink=auto", src, dest] + then ["--reflink=auto", src', dest'] else if SysConfig.cp_a - then ["-a", src, dest] + then ["-a", src', dest'] else if SysConfig.cp_p - then ["-p", src, dest] - else [src, dest] + then ["-p", src', dest'] + else [src', dest'] + src' = utilityEscape src + dest' = utilityEscape dest diff --git a/Remotes.hs b/Remotes.hs index 15f5185b9..c7e69aad8 100644 --- a/Remotes.hs +++ b/Remotes.hs @@ -282,7 +282,7 @@ rsyncParams r sending key file = do -- inplace makes rsync resume partial files options = ["-p", "--progress", "--inplace"] -- the rsync shell parameter controls where rsync - -- does, so the source/dest parameter can be a dummy value, + -- goes, so the source/dest parameter can be a dummy value, -- that just enables remote rsync mode. dummy = ":" diff --git a/RsyncFile.hs b/RsyncFile.hs index 274e66151..9de2e2c59 100644 --- a/RsyncFile.hs +++ b/RsyncFile.hs @@ -24,11 +24,12 @@ rsyncShell command = ["-e", unwords $ map escape command] {- Runs rsync in server mode to send a file, and exits. -} rsyncServerSend :: FilePath -> IO () -rsyncServerSend file = rsyncExec $ rsyncServerParams ++ ["--sender", file] +rsyncServerSend file = rsyncExec $ + rsyncServerParams ++ ["--sender", utilityEscape file] {- Runs rsync in server mode to receive a file. -} rsyncServerReceive :: FilePath -> IO Bool -rsyncServerReceive file = rsync $ rsyncServerParams ++ [file] +rsyncServerReceive file = rsync $ rsyncServerParams ++ [utilityEscape file] rsyncServerParams :: [String] rsyncServerParams = diff --git a/Utility.hs b/Utility.hs index 89e129181..6a90e3cd5 100644 --- a/Utility.hs +++ b/Utility.hs @@ -15,6 +15,7 @@ module Utility ( boolSystem, shellEscape, shellUnEscape, + utilityEscape, unsetFileMode, readMaybe, safeWriteFile, @@ -179,6 +180,13 @@ shellUnEscape s = word:(shellUnEscape rest) | c == q = findword w cs | otherwise = inquote q (w++[c]) cs +{- Ensures that a filename is safe to pass to a utility program. In particular + - since utilities tend to interpret things starting with a dash as + - an option, relative filenames starting with a dash are escaped. -} +utilityEscape :: FilePath -> FilePath +utilityEscape ('-':s) = "./-" ++ s +utilityEscape s = s + {- For quickcheck. -} prop_idempotent_shellEscape :: String -> Bool prop_idempotent_shellEscape s = [s] == (shellUnEscape $ shellEscape s) diff --git a/debian/changelog b/debian/changelog index 173c441b0..d63422324 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,9 @@ git-annex (0.22) UNRELEASED; urgency=low for his help eliminating the infestation... for now.) * Make test suite not rely on a working cp -pr. (The Unix wars are still ON!) + * Support filenames that start with a dash; when such a file is passed + to a utility it will be escaped to avoid it being interpreted as an + option. -- Joey Hess <joeyh@debian.org> Sun, 13 Feb 2011 00:48:02 -0400 diff --git a/doc/bugs/error_with_file_names_starting_with_dash.mdwn b/doc/bugs/error_with_file_names_starting_with_dash.mdwn index 7a4d33911..84bf1cfa0 100644 --- a/doc/bugs/error_with_file_names_starting_with_dash.mdwn +++ b/doc/bugs/error_with_file_names_starting_with_dash.mdwn @@ -10,3 +10,6 @@ add -wut-a-directory-name-/file1 (checksum...) sha1sum: invalid option -- 'u' git-annex: <file descriptor: 15>: hGetLine: end of file """]] + +> This is fixed in git, at least I think I've found all cases where +> filenames are passed to programs and escaped them. --[[Joey]] [[done]] |