summaryrefslogtreecommitdiff
path: root/Utility
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-03-22 17:09:54 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-03-22 17:32:47 -0400
commite38a839a80ae70eba13b6fd0e7ee08be8a62c513 (patch)
treec6f3faf1df29c0d9ddf7458554661ee4e50c9aed /Utility
parentf1398b558316a936690a8f3b01493f498d15b659 (diff)
Rewrote free disk space checking code
Moving the portability handling into a small C library cleans up things a lot, avoiding the pain of unpacking structs from inside haskell code.
Diffstat (limited to 'Utility')
-rw-r--r--Utility/DiskFree.hs32
-rw-r--r--Utility/StatFS.hsc128
-rw-r--r--Utility/diskfree.c61
-rw-r--r--Utility/diskfree.h1
4 files changed, 94 insertions, 128 deletions
diff --git a/Utility/DiskFree.hs b/Utility/DiskFree.hs
new file mode 100644
index 000000000..e02794954
--- /dev/null
+++ b/Utility/DiskFree.hs
@@ -0,0 +1,32 @@
+{- disk free space checking
+ -
+ - Copyright 2012 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+module Utility.DiskFree ( getDiskFree ) where
+
+import Common
+
+import Foreign.C.Types
+import Foreign.C.String
+import Foreign.C.Error
+
+foreign import ccall unsafe "diskfree.h diskfree" c_diskfree
+ :: CString -> IO CULLong
+
+getDiskFree :: String -> IO (Maybe Integer)
+getDiskFree path = withFilePath path $ \c_path -> do
+ free <- c_diskfree c_path
+ ifM (safeErrno <$> getErrno)
+ ( return $ Just $ toInteger free
+ , do
+ Errno i <- getErrno
+ print i
+ return Nothing
+ )
+ where
+ safeErrno (Errno v) = v == 0
diff --git a/Utility/StatFS.hsc b/Utility/StatFS.hsc
deleted file mode 100644
index ed4c9f1cb..000000000
--- a/Utility/StatFS.hsc
+++ /dev/null
@@ -1,128 +0,0 @@
------------------------------------------------------------------------------
--- |
---
--- (This code originally comes from xmobar)
---
--- Module : StatFS
--- Copyright : (c) Jose A Ortega Ruiz
--- License : BSD-3-clause
---
--- All rights reserved.
---
--- 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 author nor the names of his 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 AUTHORS 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.
---
--- Maintainer : Jose A Ortega Ruiz <jao@gnu.org>
--- Stability : unstable
--- Portability : unportable
---
--- A binding to C's statvfs(2)
---
------------------------------------------------------------------------------
-
-{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}
-
-
-module Utility.StatFS ( FileSystemStats(..), getFileSystemStats ) where
-
-import Utility.FileSystemEncoding
-
-import Foreign
-import Foreign.C.Types
-import Foreign.C.String
-
-#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__) || defined (__APPLE__)
-# include <sys/param.h>
-# include <sys/mount.h>
-#else
-#if defined (__linux__)
-#include <sys/vfs.h>
-#else
-#define UNKNOWN
-#endif
-#endif
-
-data FileSystemStats = FileSystemStats {
- fsStatBlockSize :: Integer
- -- ^ Optimal transfer block size.
- , fsStatBlockCount :: Integer
- -- ^ Total data blocks in file system.
- , fsStatByteCount :: Integer
- -- ^ Total bytes in file system.
- , fsStatBytesFree :: Integer
- -- ^ Free bytes in file system.
- , fsStatBytesAvailable :: Integer
- -- ^ Free bytes available to non-superusers.
- , fsStatBytesUsed :: Integer
- -- ^ Bytes used.
- } deriving (Show, Eq)
-
-data CStatfs
-
-#ifdef UNKNOWN
-#warning free space checking code not available for this OS
-#else
-#if defined(__APPLE__)
-foreign import ccall unsafe "sys/mount.h statfs64"
-#else
-#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__)
-foreign import ccall unsafe "sys/mount.h statfs"
-#else
-foreign import ccall unsafe "sys/vfs.h statfs64"
-#endif
-#endif
- c_statfs :: CString -> Ptr CStatfs -> IO CInt
-#endif
-
-toI :: CULong -> Integer
-toI = toInteger
-
-getFileSystemStats :: String -> IO (Maybe FileSystemStats)
-getFileSystemStats path =
-#ifdef UNKNOWN
- return Nothing
-#else
- allocaBytes (#size struct statfs) $ \vfs ->
- withFilePath path $ \cpath -> do
- res <- c_statfs cpath vfs
- if res == -1 then return Nothing
- else do
- bsize <- (#peek struct statfs, f_bsize) vfs
- bcount <- (#peek struct statfs, f_blocks) vfs
- bfree <- (#peek struct statfs, f_bfree) vfs
- bavail <- (#peek struct statfs, f_bavail) vfs
- let bpb = toI bsize
- let stats = FileSystemStats
- { fsStatBlockSize = bpb
- , fsStatBlockCount = toI bcount
- , fsStatByteCount = toI bcount * bpb
- , fsStatBytesFree = toI bfree * bpb
- , fsStatBytesAvailable = toI bavail * bpb
- , fsStatBytesUsed = toI (bcount - bfree) * bpb
- }
- if fsStatBlockCount stats == 0 || fsStatBlockSize stats == 0
- then return Nothing
- else return $ Just stats
-#endif
diff --git a/Utility/diskfree.c b/Utility/diskfree.c
new file mode 100644
index 000000000..9ac31a752
--- /dev/null
+++ b/Utility/diskfree.c
@@ -0,0 +1,61 @@
+/* disk free space checking, C mini-library
+ *
+ * Copyright 2012 Joey Hess <joey@kitenet.net>
+ *
+ * Licensed under the GNU GPL version 3 or higher.
+ */
+
+/* Include appropriate headers for the OS, and define what will be used to
+ * check the free space. */
+#if defined(__APPLE__)
+# include <sys/param.h>
+# include <sys/mount.h>
+# define STATSTRUCT statfs
+# define STATCALL statfs64
+#else
+#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
+# include <sys/param.h>
+# include <sys/mount.h>
+# define STATSTRUCT statfs
+# define STATCALL statfs
+#else
+#if defined (__linux__)
+# include <sys/statvfs.h>
+# define STATSTRUCT statvfs
+# define STATCALL statvfs
+#else
+# warning free space checking code not available for this OS
+# define UNKNOWN
+#endif
+#endif
+#endif
+
+#include <errno.h>
+
+/* Checks the amount of disk that is available to regular (non-root) users.
+ * (If there's an error, or this is not supported,
+ * returns 0 and sets errno to nonzero.)
+ */
+unsigned long long int diskfree(const char *path) {
+#ifdef UNKNOWN
+ errno = 1;
+ return 0;
+#else
+ unsigned long long int available, blocksize;
+ struct STATSTRUCT buf;
+
+ errno = 0;
+ if (STATCALL(path, &buf) != 0)
+ return 0; /* errno is set */
+
+ available = buf.f_bavail;
+ blocksize = buf.f_bsize;
+ return available * blocksize;
+#endif
+}
+
+/*
+main () {
+ printf("%lli\n", diskfree("."));
+}
+*/
diff --git a/Utility/diskfree.h b/Utility/diskfree.h
new file mode 100644
index 000000000..e5b84754f
--- /dev/null
+++ b/Utility/diskfree.h
@@ -0,0 +1 @@
+unsigned long long int diskfree(const char *path);