adb send to final filename not tmp file

Avoids some problems with unusual character in exporttree filenames
that confuse adb shell commands.

In particular, with a filename that contains \351, adb push sends the file
to the correct filename in /sdcard. And running find on the android device
roundtrips the filename. But, running mv on that filename on the android
device fails with "bad <filename>: No such file or directory".
Interestingly, ls on android works, and rm fails.

adb push to the final name to avoids this problem. But what about
atomicity? Well, I tried an adb push and interrupted it part way through.
The file was present while the push was running, but was removed once the
push got interrupted. I also tried yanking the cable while adb push was
running, and the partially received file was also deleted then. That avoids
most problems.

An import that runs at the same time as an export will see the partially
sent file. But that is unlikely to be done, and if it did happen, it would
notice that the imported file had changed in the meantime and discard it.

Note that, since rm on the android device fails on these filenames,
exporting a tree where the file is deleted is going to fail to remove it. I
don't see what I can do about that, so long as android is using an rm that
has issues with filename encodings.

This was tested on a phone where find, ls, and rm all come from Toybox 0.8.6.

Sponsored-by: unqueued on Patreon
This commit is contained in:
Joey Hess 2023-09-11 13:13:05 -04:00
parent c7346c2c47
commit 29ae536637
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 6 additions and 18 deletions

View file

@ -7,6 +7,8 @@ git-annex (10.20230829) UNRELEASED; urgency=medium
safe.bareRepository = explicit. safe.bareRepository = explicit.
* Removed the vendored git-lfs and the GitLfs build flag. * Removed the vendored git-lfs and the GitLfs build flag.
* Fix linker optimisation in linux standalone tarballs. * Fix linker optimisation in linux standalone tarballs.
* adb: Avoid some problems with unusual character in exporttree
filenames that confuse adb shell commands.
-- Joey Hess <id@joeyh.name> Mon, 28 Aug 2023 13:10:17 -0400 -- Joey Hess <id@joeyh.name> Mon, 28 Aug 2023 13:10:17 -0400

View file

@ -183,24 +183,12 @@ store serial adir = fileStorer $ \k src _p ->
giveup "adb failed" giveup "adb failed"
store' :: AndroidSerial -> AndroidPath -> FilePath -> Annex Bool store' :: AndroidSerial -> AndroidPath -> FilePath -> Annex Bool
store' serial dest src = store'' serial dest src (return True) store' serial dest src = checkAdbInPath False $ do
store'' :: AndroidSerial -> AndroidPath -> FilePath -> Annex Bool -> Annex Bool
store'' serial dest src canoverwrite = checkAdbInPath False $ do
let destdir = takeDirectory $ fromAndroidPath dest let destdir = takeDirectory $ fromAndroidPath dest
void $ adbShell serial [Param "mkdir", Param "-p", File destdir] void $ adbShell serial [Param "mkdir", Param "-p", File destdir]
showOutput -- make way for adb push output showOutput -- make way for adb push output
let tmpdest = fromAndroidPath dest ++ ".annextmp" liftIO $ boolSystem "adb" $ mkAdbCommand serial
ifM (liftIO $ boolSystem "adb" (mkAdbCommand serial [Param "push", File src, File tmpdest])) [Param "push", File src, File (fromAndroidPath dest)]
( ifM canoverwrite
-- move into place atomically
( adbShellBool serial [Param "mv", File tmpdest, File (fromAndroidPath dest)]
, do
void $ remove' serial (AndroidPath tmpdest)
return False
)
, return False
)
retrieve :: AndroidSerial -> AndroidPath -> Retriever retrieve :: AndroidSerial -> AndroidPath -> Retriever
retrieve serial adir = fileRetriever $ \dest k _p -> retrieve serial adir = fileRetriever $ \dest k _p ->
@ -385,10 +373,8 @@ retrieveExportWithContentIdentifierM serial adir loc cids dest gk _p = do
storeExportWithContentIdentifierM :: AndroidSerial -> AndroidPath -> FilePath -> Key -> ExportLocation -> [ContentIdentifier] -> MeterUpdate -> Annex ContentIdentifier storeExportWithContentIdentifierM :: AndroidSerial -> AndroidPath -> FilePath -> Key -> ExportLocation -> [ContentIdentifier] -> MeterUpdate -> Annex ContentIdentifier
storeExportWithContentIdentifierM serial adir src _k loc overwritablecids _p = storeExportWithContentIdentifierM serial adir src _k loc overwritablecids _p =
-- Check if overwrite is safe before sending, because sending the
-- file is expensive and don't want to do it unncessarily.
ifM checkcanoverwrite ifM checkcanoverwrite
( ifM (store'' serial dest src checkcanoverwrite) ( ifM (store' serial dest src)
( getExportContentIdentifier serial adir loc >>= \case ( getExportContentIdentifier serial adir loc >>= \case
Right (Just cid) -> return cid Right (Just cid) -> return cid
Right Nothing -> giveup "adb failed to store file" Right Nothing -> giveup "adb failed to store file"