From d35132810ae8d9c13d8b80004ab9c1a2544d671c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 4 May 2013 16:04:17 -0400 Subject: [PATCH] Got removable media mount detection working on Android. Bionic has an amusing stub for `getmntent` that prints out "FIX ME! implement getmntent()" But, `/proc/mounts` is there, so I just parse it. --- Assistant/WebApp/Configurators/Local.hs | 4 ++++ Assistant/WebApp/Configurators/Ssh.hs | 6 ++--- Utility/Mounts.hsc | 30 +++++++++++++++++++++++-- Utility/libmounts.h | 2 +- doc/design/assistant/android.mdwn | 4 +--- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Assistant/WebApp/Configurators/Local.hs b/Assistant/WebApp/Configurators/Local.hs index ea42793df7..cb366db8f2 100644 --- a/Assistant/WebApp/Configurators/Local.hs +++ b/Assistant/WebApp/Configurators/Local.hs @@ -300,6 +300,10 @@ driveList = mapM (gen . mnt_dir) =<< filter sane <$> getMounts | dir == "/tmp" = False | dir == "/run/shm" = False | dir == "/run/lock" = False +#ifdef __ANDROID__ + | dir == "/mnt/sdcard" = False + | dir == "/sdcard" = False +#endif | otherwise = True #else driveList = return [] diff --git a/Assistant/WebApp/Configurators/Ssh.hs b/Assistant/WebApp/Configurators/Ssh.hs index 2376ee548b..c3edbd3912 100644 --- a/Assistant/WebApp/Configurators/Ssh.hs +++ b/Assistant/WebApp/Configurators/Ssh.hs @@ -65,9 +65,9 @@ sshInputAForm hostnamefield def = SshInput <*> aopt textField "Directory" (Just $ Just $ fromMaybe (T.pack gitAnnexAssistantDefaultDir) $ inputDirectory def) <*> areq intField "Port" (Just $ inputPort def) where +#ifndef __ANDROID__ check_hostname = checkM (liftIO . checkdns) hostnamefield checkdns t = do -#ifndef __ANDROID__ let h = T.unpack t let canonname = Just $ defaultHints { addrFlags = [AI_CANONNAME] } r <- catchMaybeIO $ getAddrInfo canonname (Just h) Nothing @@ -79,8 +79,8 @@ sshInputAForm hostnamefield def = SshInput Just [] -> Right t Nothing -> Left bad_hostname #else - -- getAddrInfo currently broken on Android - return $ Right t + -- getAddrInfo currently broken on Android + check_hostname = hostnamefield -- unchecked #endif check_username = checkBool (all (`notElem` "/:@ \t") . T.unpack) diff --git a/Utility/Mounts.hsc b/Utility/Mounts.hsc index c21a68032e..c13b0ece11 100644 --- a/Utility/Mounts.hsc +++ b/Utility/Mounts.hsc @@ -3,7 +3,7 @@ - Derived from hsshellscript, originally written by - Volker Wysk - - - Modified to support BSD and Mac OS X by + - Modified to support BSD, Mac OS X, and Android by - Joey Hess - - Licensed under the GNU LGPL version 2.1 or higher. @@ -16,13 +16,18 @@ module Utility.Mounts ( getMounts ) where +#ifndef __ANDROID__ import Control.Monad import Foreign import Foreign.C import GHC.IO hiding (finally, bracket) import Prelude hiding (catch) - #include "libmounts.h" +#else +import Utility.Exception +import Data.Maybe +import Control.Applicative +#endif {- This is a stripped down mntent, containing only - fields available everywhere. -} @@ -32,6 +37,8 @@ data Mntent = Mntent , mnt_type :: String } deriving (Read, Show, Eq, Ord) +#ifndef __ANDROID__ + getMounts :: IO [Mntent] getMounts = do h <- c_mounts_start @@ -67,3 +74,22 @@ foreign import ccall unsafe "libmounts.h mounts_next" c_mounts_next :: Ptr () -> IO (Ptr ()) foreign import ccall unsafe "libmounts.h mounts_end" c_mounts_end :: Ptr () -> IO CInt + +#else + +{- Android does not support getmntent (well, it's a no-op stub in Bionic). + - + - But, the linux kernel's /proc/mounts is available to be parsed. + -} +getMounts :: IO [Mntent] +getMounts = catchDefaultIO [] $ + mapMaybe (parse . words) . lines <$> readFile "/proc/mounts" + where + parse (device:mountpoint:fstype:_rest) = Just $ Mntent + { mnt_fsname = device + , mnt_dir = mountpoint + , mnt_type = fstype + } + parse _ = Nothing + +#endif diff --git a/Utility/libmounts.h b/Utility/libmounts.h index 460fcc7abd..24df55f310 100644 --- a/Utility/libmounts.h +++ b/Utility/libmounts.h @@ -6,7 +6,7 @@ # define GETMNTINFO #else #if defined __ANDROID__ -# warning mounts listing code not available for Android +/* Android is handled by the Haskell code, not here. */ # define UNKNOWN #else #if defined (__linux__) || defined (__FreeBSD_kernel__) diff --git a/doc/design/assistant/android.mdwn b/doc/design/assistant/android.mdwn index 2a2609341d..4b1a468e58 100644 --- a/doc/design/assistant/android.mdwn +++ b/doc/design/assistant/android.mdwn @@ -28,8 +28,6 @@ * Ssh server and Rsync.net configuration stops where ssh should be prompting for a password in the terminal. * Enabling debug logging in the webapp doesn't seem to work. -* S3, glacier, and local pairing are not yet enabled for Android. +* glacier and local pairing are not yet enabled for Android. * The "Files" link doesn't start a file browser. Should be possible to do on Android via intents, I suppose? -* Does not detect mounted USB drives. getMounts is failing - probably?