From 107a7b9388077a2b7fe9ce107da3a4a5fa396e2e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Thu, 19 Jul 2012 20:38:58 -0400 Subject: try to make Utility.Mounts portable This is an unholy mashup, but it just might work. It works on Linux, that's all I've tested. :) --- Assistant/Threads/MountWatcher.hs | 2 +- Makefile | 4 +- Utility/Mounts.hsc | 58 ++++++++------------- Utility/libmounts.c | 105 ++++++++++++++++++++++++++++++++++++++ Utility/libmounts.h | 48 +++++++++++++++++ debian/copyright | 13 ++++- git-annex.cabal | 2 +- 7 files changed, 190 insertions(+), 42 deletions(-) create mode 100644 Utility/libmounts.c create mode 100644 Utility/libmounts.h diff --git a/Assistant/Threads/MountWatcher.hs b/Assistant/Threads/MountWatcher.hs index f3b9c0a3a..cc62c294d 100644 --- a/Assistant/Threads/MountWatcher.hs +++ b/Assistant/Threads/MountWatcher.hs @@ -82,7 +82,7 @@ type MountPoints = S.Set FilePath {- Reads mtab, getting the current set of mount points. -} currentMountPoints :: IO MountPoints -currentMountPoints = S.fromList . map mnt_dir <$> read_mtab +currentMountPoints = S.fromList . map mnt_dir <$> getMounts {- Finds new mount points, given an old and a new set. -} newMountPoints :: MountPoints -> MountPoints -> MountPoints diff --git a/Makefile b/Makefile index 1791d4339..a6030efa1 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ all=$(bins) $(mans) docs OS:=$(shell uname | sed 's/[-_].*//') ifeq ($(OS),Linux) BASEFLAGS_OPTS+=-DWITH_INOTIFY -DWITH_DBUS -clibs=Utility/libdiskfree.o +clibs=Utility/libdiskfree.o Utility/libmounts.o else BASEFLAGS_OPTS+=-DWITH_KQUEUE -clibs=Utility/libdiskfree.o Utility/libkqueue.o +clibs=Utility/libdiskfree.o Utility/libmounts.o Utility/libkqueue.o endif PREFIX=/usr diff --git a/Utility/Mounts.hsc b/Utility/Mounts.hsc index 622ac877a..6bcb03f2c 100644 --- a/Utility/Mounts.hsc +++ b/Utility/Mounts.hsc @@ -2,6 +2,9 @@ - - Derived from hsshellscript, originally written by - Volker Wysk + - + - Modified to support BSD and Mac OS X by + - Joey Hess - - Licensed under the GNU LGPL version 2.1 or higher. -} @@ -10,8 +13,7 @@ module Utility.Mounts ( Mntent(..), - read_mtab, - read_fstab, + getMounts ) where import Control.Monad @@ -20,62 +22,46 @@ import Foreign.C import GHC.IO hiding (finally, bracket) import Prelude hiding (catch) -#include -#include +#include "libmounts.h" +{- This is a stripped down mntent, containing only + - fields available everywhere. -} data Mntent = Mntent { mnt_fsname :: String , mnt_dir :: String , mnt_type :: String - , mnt_opts :: String - , mnt_freq :: Int - , mnt_passno :: Int } deriving (Read, Show, Eq) -read_mounts :: String -> IO [Mntent] -read_mounts path = do - h <- withCString path $ \cpath -> - withCString "r" $ \r -> - c_setmntent cpath r +getMounts :: IO [Mntent] +getMounts = do + h <- c_mounts_start when (h == nullPtr) $ - throwErrno "setmntent" + throwErrno "getMounts" mntent <- getmntent h [] - _ <- c_endmntent h + _ <- c_mounts_end h return mntent where - getmntent h l = do - ptr <- c_getmntent h + getmntent h c = do + ptr <- c_mounts_next h if (ptr == nullPtr) - then return $ reverse l + then return $ reverse c else do mnt_fsname_str <- #{peek struct mntent, mnt_fsname} ptr >>= peekCString mnt_dir_str <- #{peek struct mntent, mnt_dir} ptr >>= peekCString mnt_type_str <- #{peek struct mntent, mnt_type} ptr >>= peekCString - mnt_opts_str <- #{peek struct mntent, mnt_opts} ptr >>= peekCString - mnt_freq_int <- #{peek struct mntent, mnt_freq} ptr - mnt_passno_int <- #{peek struct mntent, mnt_passno} ptr let ent = Mntent { mnt_fsname = mnt_fsname_str , mnt_dir = mnt_dir_str , mnt_type = mnt_type_str - , mnt_opts = mnt_opts_str - , mnt_freq = mnt_freq_int - , mnt_passno = mnt_passno_int } - getmntent h (ent:l) - -read_mtab :: IO [Mntent] -read_mtab = read_mounts "/etc/mtab" - -read_fstab :: IO [Mntent] -read_fstab = read_mounts "/etc/fstab" + getmntent h (ent:c) -foreign import ccall safe "setmntent" - c_setmntent :: ((Ptr CChar) -> ((Ptr CChar) -> (IO (Ptr ())))) +foreign import ccall unsafe "libmounts.h mounts_start" c_mounts_start + :: IO (Ptr ()) -foreign import ccall safe "endmntent" - c_endmntent :: ((Ptr ()) -> (IO CInt)) +foreign import ccall unsafe "libmounts.h mounts_next" c_mounts_next + :: Ptr () -> IO (Ptr ()) -foreign import ccall safe "getmntent" - c_getmntent :: ((Ptr ()) -> (IO (Ptr ()))) +foreign import ccall unsafe "libmounts.h mounts_end" c_mounts_end + :: Ptr () -> IO CInt diff --git a/Utility/libmounts.c b/Utility/libmounts.c new file mode 100644 index 000000000..00755c577 --- /dev/null +++ b/Utility/libmounts.c @@ -0,0 +1,105 @@ +/* mounted filesystems, C mini-library + * + * Copyright (c) 1980, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2001 + * David Rufino + * Copyright 2012 + * Joey Hess + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "libmounts.h" + +#include +#include + +#ifdef GETMNTENT +/* direct passthrough the getmntent */ +FILE *mounts_start (void) { + return setmntent("/etc/mtab", "r"); +} +int mounts_end (FILE *fp) { + return endmntent(fp); +} +struct mntent *mounts_next (FILE *fp) { + return getmntent(fp); +} +#endif + +#ifdef GETMNTINFOCALL +/* getmntent emulation using getmntinfo */ +FILE *mounts_start (void) { + return ((FILE *)0x1) /* dummy non-NULL FILE pointer, not used */ +} +int mounts_end (FILE *fp) { + return 1; +} + +static struct mntent _mntent; + +static struct mntent *statfs_to_mntent (struct MNTINFOSTRUCT *mntbuf) { + _mntent.mnt_fsname = mntbuf->f_mntfromname; + _mntent.mnt_dir = mntbuf->f_mntonname; + _mntent.mnt_type = mntbuf->f_fstypename; + + _mntent.mnt_opts = '\0'; + _mntent.mnt_freq = 0; + _mntent.mnt_passno = 0; + + return (&_mntent); +} + +static int pos = -1; +static int mntsize = -1; + +struct mntent *mounts_next (FILE *fp) { + struct MNTINFOSTRUCT *mntbuf; + + if (pos == -1 || mntsize == -1) + mntsize = GETMNTINFOCALL(&mntbuf, MNT_NOWAIT); + ++pos; + if (pos == mntsize) { + pos = mntsize = -1; + return NULL; + } + + return (statfs_to_mntent(&mntbuf[pos])); +} +#endif + +#ifdef UNKNOWN +/* dummy, do-nothing version */ +FILE *mounts_start (void) { + return ((FILE *)0x1); +} +int mounts_end (FILE *fp) { + return 1; +} +struct mntent *mounts_next (FILE *fp) { + return NULL; +} +#endif diff --git a/Utility/libmounts.h b/Utility/libmounts.h new file mode 100644 index 000000000..0bd52e323 --- /dev/null +++ b/Utility/libmounts.h @@ -0,0 +1,48 @@ +/* Include appropriate headers for the OS, and define what will be used. */ +#if defined(__APPLE__) +# include +# include +# include +/* In newer OSX versions, statfs64 is deprecated, in favor of statfs, + * which is 64 bit only with a build option -- but statfs64 still works, + * and this keeps older OSX also supported. */ +# define GETMNTINFOCALL getmntinfo64 +# define MNTINFOSTRUCT statfs64 +#else +#if defined (__FreeBSD__) +# include +# include +# include +# define GETMNTINFOCALL getmntinfo64 +# define MNTINFOSTRUCT statfs64 +#else +#if defined (__linux__) || defined (__FreeBSD_kernel__) +/* Linux or Debian kFreeBSD */ +#include +# define GETMNTENT +#else +# warning mounts listing code not available for this OS +# define UNKNOWN +#endif +#endif +#endif + +#include +#include +#include + +#ifndef GETMNTENT +#warning "boo" +struct mntent { + char *mnt_fsname; + char *mnt_dir; + char *mnt_type; + char *mnt_opts; /* not filled in */ + int mnt_freq; /* not filled in */ + int mnt_passno; /* not filled in */ +}; +#endif + +FILE *mounts_start (void); +int mounts_end (FILE *fp); +struct mntent *mounts_next (FILE *fp); diff --git a/debian/copyright b/debian/copyright index dcfbaf3e3..26a559cc5 100644 --- a/debian/copyright +++ b/debian/copyright @@ -8,13 +8,22 @@ License: GPL-3+ this package's source, or in /usr/share/common-licenses/GPL-3 on Debian systems. -Files: Utility/Mtab.hcs +Files: Utility/Mounts.hsc Copyright: Volker Wysk License: LGPL-2.1+ - the full text of version 2.1 of the LGPL is distributed as doc/LGPL + The full text of version 2.1 of the LGPL is distributed as doc/LGPL in this package's source, or in /usr/share/common-licences/LGPL-2.1 on Debian systems. +Files: Utility/libmounts.c +Copyright: 1980, 1989, 1993, 1994 The Regents of the University of California + 2001 David Rufino + 2012 Joey Hess +License: BSD-3-clause + The full test of the 3 clause BSD license is distributed inside + Utility/libmounts.c in this package's source, or in + /usr/share/common-licenses/BSD on Debian systems. + Files: doc/logo.png doc/logo_small.png doc/favicon.png Copyright: 2007 Henrik Nyh 2010 Joey Hess diff --git a/git-annex.cabal b/git-annex.cabal index 00f57319d..be752f844 100644 --- a/git-annex.cabal +++ b/git-annex.cabal @@ -46,7 +46,7 @@ Executable git-annex IfElse, text, QuickCheck >= 2.1, bloomfilter, edit-distance, process -- Need to list these because they're generated from .hsc files. Other-Modules: Utility.Touch Utility.Mounts - C-Sources: Utility/libdiskfree.c + C-Sources: Utility/libdiskfree.c Utility/libmounts.c Extensions: CPP GHC-Options: -threaded -- cgit v1.2.3