summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-02-25 01:13:01 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-02-25 01:13:01 -0400
commit836e71297b8e3b5bd6f89f7eb1198f59af985b0b (patch)
tree835db9db776b23552736422baf9794eb6a3ac5e5
parente61b47bc8a51447f9fbde6463e09d4beef8d5a7f (diff)
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.
-rw-r--r--Backend/SHA1.hs3
-rw-r--r--Backend/URL.hs2
-rw-r--r--Command/SetKey.hs3
-rw-r--r--CopyFile.hs10
-rw-r--r--Remotes.hs2
-rw-r--r--RsyncFile.hs5
-rw-r--r--Utility.hs8
-rw-r--r--debian/changelog3
-rw-r--r--doc/bugs/error_with_file_names_starting_with_dash.mdwn3
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]]