diff options
author | Joey Hess <joey@kitenet.net> | 2012-03-22 17:09:54 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-03-22 17:32:47 -0400 |
commit | e38a839a80ae70eba13b6fd0e7ee08be8a62c513 (patch) | |
tree | c6f3faf1df29c0d9ddf7458554661ee4e50c9aed /Utility | |
parent | f1398b558316a936690a8f3b01493f498d15b659 (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.hs | 32 | ||||
-rw-r--r-- | Utility/StatFS.hsc | 128 | ||||
-rw-r--r-- | Utility/diskfree.c | 61 | ||||
-rw-r--r-- | Utility/diskfree.h | 1 |
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); |