diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,5 @@
+mountpoints (1.0.0) unstable; urgency=low
+
+  * Initial release, extracted from git-annex.
+
+ -- Joey Hess <id@joeyh.name>  Sun, 14 Feb 2016 20:39:23 -0400
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,40 @@
+haskell library license:
+
+-- Copyright: 2012 Joey Hess <id@joeyh.name>
+-- License: LGPL 2.1 or higher
+--
+-- Derived from hsshellscript, originally written by
+-- Volker Wysk <hsss@volker-wysk.de>
+
+C library license:
+
+ * Copyright (c) 1980, 1989, 1993, 1994
+ *      The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2001
+ *      David Rufino <daverufino@btinternet.com>
+ * Copyright 2012
+ *      Joey Hess <id@joeyh.name>
+ *
+ * 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.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+{- cabal setup file -}
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/System/MountPoints.hsc b/System/MountPoints.hsc
new file mode 100644
--- /dev/null
+++ b/System/MountPoints.hsc
@@ -0,0 +1,87 @@
+-- | 
+-- Copyright: 2012 Joey Hess <id@joeyh.name>
+-- License: LGPL 2.1 or higher
+-- 
+-- Derived from hsshellscript, originally written by
+-- Volker Wysk <hsss@volker-wysk.de>
+
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module System.MountPoints (
+	Mntent(..),
+	getMounts,
+	getProcMounts,
+) where
+
+#include "libmounts.h"
+import Control.Monad
+import Control.Exception
+import Data.Maybe
+import Control.Applicative
+import Foreign
+import Foreign.C
+import Prelude
+
+-- | This is a stripped down mntent, containing only fields available
+-- everywhere.
+data Mntent = Mntent
+	{ mnt_fsname :: String -- ^ what's mounted
+	, mnt_dir :: FilePath  -- ^ where it's mounted
+	, mnt_type :: String   -- ^ what sort of filesystem is mounted
+	} deriving (Show, Eq, Ord)
+
+-- | Get currently mounted filesystems.
+--
+-- This uses eiher getmntent or getmntinfo, depending on the OS.
+getMounts :: IO [Mntent]
+getMounts = do
+	h <- c_mounts_start
+	when (h == nullPtr) $
+		throwErrno "getMounts"
+	mntent <- getmntent h []
+	_ <- c_mounts_end h
+	return mntent
+  where
+	getmntent h c = do
+		ptr <- c_mounts_next h
+		if ptr == nullPtr
+			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
+				let ent = Mntent
+					{ mnt_fsname = mnt_fsname_str
+					, mnt_dir = mnt_dir_str
+					, mnt_type = mnt_type_str
+					}
+				getmntent h (ent:c)
+
+-- Using unsafe imports because the C functions are belived to never block.
+-- Note that getmntinfo is called with MNT_NOWAIT to avoid possibly blocking;
+-- while getmntent only accesses a file in /etc (or /proc) that should not
+-- block.
+foreign import ccall unsafe "libmounts.h mounts_start" c_mounts_start
+        :: IO (Ptr ())
+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
+
+-- | Read </proc/mounts> to get currently mounted filesystems.
+-- 
+-- This works on Linux and related systems, including Android. 
+-- Note that on Android, `getMounts` will always return [], so
+-- use this instead.
+getProcMounts :: IO [Mntent]
+getProcMounts = do
+	v <- try go :: IO (Either SomeException [Mntent])
+	return (either (const []) id v)
+  where
+	go = mapMaybe (parse . words) . lines <$> readFile "/proc/mounts"
+  	parse (device:mountpoint:fstype:_rest) = Just $ Mntent
+		{ mnt_fsname = device
+		, mnt_dir = mountpoint
+		, mnt_type = fstype
+		}
+	parse _ = Nothing
diff --git a/cbits/libmounts.c b/cbits/libmounts.c
new file mode 100644
--- /dev/null
+++ b/cbits/libmounts.c
@@ -0,0 +1,103 @@
+/* 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 <daverufino@btinternet.com>
+ * Copyright 2012
+ *      Joey Hess <id@joeyh.name>
+ *
+ * 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"
+
+#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 GETMNTINFO
+/* 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 statfs *mntbuf) {
+	_mntent.mnt_fsname = mntbuf->f_mntfromname;
+	_mntent.mnt_dir = mntbuf->f_mntonname;
+	_mntent.mnt_type = mntbuf->f_fstypename;
+
+	_mntent.mnt_opts = NULL;
+	_mntent.mnt_freq = 0;
+	_mntent.mnt_passno = 0;
+
+	return (&_mntent);
+}
+
+static int pos = -1;
+static int mntsize = -1;
+struct statfs *mntbuf = NULL;
+
+struct mntent *mounts_next (FILE *fp) {
+
+	if (pos == -1 || mntsize == -1)
+		mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+	++pos;
+	if (pos == mntsize) {
+		pos = mntsize = -1;
+		mntbuf = NULL;
+		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/cbits/libmounts.h b/cbits/libmounts.h
new file mode 100644
--- /dev/null
+++ b/cbits/libmounts.h
@@ -0,0 +1,33 @@
+/* Include appropriate headers for the OS, and define what will be used. */
+#if defined (__FreeBSD__) || defined (__APPLE__)
+# include <sys/param.h>
+# include <sys/ucred.h>
+# include <sys/mount.h>
+# define GETMNTINFO
+#else
+#if defined (__linux__) || defined (__FreeBSD_kernel__)
+/* Linux or Debian kFreeBSD */
+#include <mntent.h>
+# define GETMNTENT
+#else
+# warning mounts listing code not available for this OS
+# define UNKNOWN
+#endif
+#endif
+
+#include <stdio.h>
+
+#ifndef GETMNTENT
+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/mountpoints.cabal b/mountpoints.cabal
new file mode 100644
--- /dev/null
+++ b/mountpoints.cabal
@@ -0,0 +1,30 @@
+Name: mountpoints
+Version: 1.0.0
+Cabal-Version: >= 1.8
+License: LGPL
+Maintainer: Joey Hess <id@joeyh.name>
+Author: Joey Hess
+Stability: Stable
+Copyright: 2012 Joey Hess
+License-File: LICENSE
+Build-Type: Simple
+Category: System
+Synopsis: list mount points
+Description:
+ Lists currently mounted filesystems.
+ .
+ Works on: Linux, BSD, Mac OS X, Android
+Extra-Source-FIles:
+ cbits/libmounts.h
+ CHANGELOG
+
+Library
+  GHC-Options: -Wall -fno-warn-tabs
+  Exposed-Modules: System.MountPoints
+  Include-Dirs: cbits
+  C-Sources: cbits/libmounts.c
+  Build-Depends: base (>= 4.5), base < 5
+
+source-repository head
+  type: git
+  location: git://git.joeyh.name/haskell-mountpoints.git
