summaryrefslogtreecommitdiff
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
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.
-rw-r--r--Annex/Content.hs16
-rw-r--r--Build/Configure.hs17
-rw-r--r--Command/Status.hs16
-rw-r--r--Config.hs18
-rw-r--r--Makefile14
-rw-r--r--Utility/DiskFree.hs32
-rw-r--r--Utility/StatFS.hsc128
-rw-r--r--Utility/diskfree.c61
-rw-r--r--Utility/diskfree.h1
-rw-r--r--configure.hs21
-rw-r--r--debian/changelog5
-rw-r--r--debian/copyright30
-rw-r--r--git-annex.cabal2
13 files changed, 124 insertions, 237 deletions
diff --git a/Annex/Content.hs b/Annex/Content.hs
index 7bb94aec2..8542d8775 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -36,7 +36,7 @@ import qualified Git
import qualified Annex
import qualified Annex.Queue
import qualified Annex.Branch
-import Utility.StatFS
+import Utility.DiskFree
import Utility.FileMode
import qualified Utility.Url as Url
import Types.Key
@@ -44,7 +44,6 @@ import Utility.DataUnits
import Utility.CopyFile
import Config
import Annex.Exception
-import qualified Build.SysConfig
{- Checks if a given key's content is currently present. -}
inAnnex :: Key -> Annex Bool
@@ -176,22 +175,19 @@ checkDiskSpace = checkDiskSpace' 0
checkDiskSpace' :: Integer -> Key -> Annex ()
checkDiskSpace' adjustment key = do
- reserve <- getDiskReserve True
- stats <- inRepo $ getFileSystemStats .gitAnnexDir
- case (cancheck, stats, keySize key) of
- (False, _, _) -> return ()
- (_, Nothing, _) -> return ()
- (_, _, Nothing) -> return ()
- (_, Just (FileSystemStats { fsStatBytesAvailable = have }), Just need) ->
+ reserve <- getDiskReserve
+ free <- inRepo $ getDiskFree . gitAnnexDir
+ case (free, keySize key) of
+ (Just have, Just need) ->
when (need + reserve > have + adjustment) $
needmorespace (need + reserve - have - adjustment)
+ _ -> return ()
where
needmorespace n = unlessM (Annex.getState Annex.force) $
error $ "not enough free space, need " ++
roughSize storageUnits True n ++
" more" ++ forcemsg
forcemsg = " (use --force to override this check or adjust annex.diskreserve)"
- cancheck = Build.SysConfig.statfs_sanity_checked == Just True
{- Moves a file into .git/annex/objects/
-
diff --git a/Build/Configure.hs b/Build/Configure.hs
index 14667ba86..341b8840d 100644
--- a/Build/Configure.hs
+++ b/Build/Configure.hs
@@ -10,12 +10,8 @@ import Control.Applicative
import Build.TestConfig
import Utility.SafeCommand
-tests :: Bool -> [TestCase]
-tests True = cabaltests ++ common
-tests False = common
-
-common :: [TestCase]
-common =
+tests :: [TestCase]
+tests =
[ TestCase "version" getVersion
, TestCase "git" $ requireCmd "git" "git --version >/dev/null"
, TestCase "git version" getGitVersion
@@ -32,11 +28,6 @@ common =
, TestCase "ssh connection caching" getSshConnectionCaching
] ++ shaTestCases [1, 256, 512, 224, 384]
-cabaltests :: [TestCase]
-cabaltests =
- [ TestCase "StatFS" testStatFSDummy
- ]
-
shaTestCases :: [Int] -> [TestCase]
shaTestCases l = map make l
where make n =
@@ -81,10 +72,6 @@ getSshConnectionCaching :: Test
getSshConnectionCaching = Config "sshconnectioncaching" . BoolConfig <$>
boolSystem "sh" [Param "-c", Param "ssh -o ControlPersist=yes -V >/dev/null 2>/dev/null"]
-testStatFSDummy :: Test
-testStatFSDummy =
- return $ Config "statfs_sanity_checked" $ MaybeBoolConfig Nothing
-
{- Set up cabal file with version. -}
cabalSetup :: IO ()
cabalSetup = do
diff --git a/Command/Status.hs b/Command/Status.hs
index aaf848905..40cefb5cc 100644
--- a/Command/Status.hs
+++ b/Command/Status.hs
@@ -22,7 +22,7 @@ import qualified Git
import qualified Annex
import Command
import Utility.DataUnits
-import Utility.StatFS
+import Utility.DiskFree
import Annex.Content
import Types.Key
import Backend
@@ -30,7 +30,6 @@ import Logs.UUID
import Logs.Trust
import Remote
import Config
-import qualified Build.SysConfig
-- a named computation that produces a statistic
type Stat = StatState (Maybe (String, StatState String))
@@ -173,19 +172,16 @@ bloom_info = stat "bloom filter size" $ json id $ do
disk_size :: Stat
disk_size = stat "available local disk space" $ json id $ lift $
- if Build.SysConfig.statfs_sanity_checked == Just True
- then calcfree
- <$> getDiskReserve False
- <*> inRepo (getFileSystemStats . gitAnnexDir)
- else return unknown
+ calcfree
+ <$> getDiskReserve
+ <*> inRepo (getDiskFree . gitAnnexDir)
where
- calcfree reserve (Just (FileSystemStats { fsStatBytesAvailable = have })) =
+ calcfree reserve (Just have) =
roughSize storageUnits True $ nonneg $ have - reserve
- calcfree _ _ = unknown
+ calcfree _ _ = "unknown"
nonneg x
| x >= 0 = x
| otherwise = 0
- unknown = "unknown"
backend_usage :: Stat
backend_usage = stat "backend usage" $ nojson $
diff --git a/Config.hs b/Config.hs
index f20298485..10a66e47b 100644
--- a/Config.hs
+++ b/Config.hs
@@ -12,7 +12,6 @@ import qualified Git
import qualified Git.Config
import qualified Git.Command
import qualified Annex
-import qualified Build.SysConfig
import Utility.DataUnits
type ConfigKey = String
@@ -92,19 +91,8 @@ getTrustLevel :: Git.Repo -> Annex (Maybe String)
getTrustLevel r = fromRepo $ Git.Config.getMaybe $ remoteConfig r "trustlevel"
{- Gets annex.diskreserve setting. -}
-getDiskReserve :: Bool -> Annex Integer
-getDiskReserve sanitycheck = do
- r <- getConfig "diskreserve" ""
- when sanitycheck $ check r
- return $ fromMaybe megabyte $ readSize dataUnits r
+getDiskReserve :: Annex Integer
+getDiskReserve = fromMaybe megabyte . readSize dataUnits
+ <$> getConfig "diskreserve" ""
where
megabyte = 1000000
- check r
- | not (null r) && not cancheck = do
- unlessM (Annex.getState Annex.force) $
- error $ "You have configured a diskreserve of "
- ++ r ++
- " but disk space checking is not working"
- return ()
- | otherwise = return ()
- cancheck = Build.SysConfig.statfs_sanity_checked == Just True
diff --git a/Makefile b/Makefile
index ddb5e3ff6..a0447f2d2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
PREFIX=/usr
IGNORE=-ignore-package monads-fd
-BASEFLAGS=-Wall $(IGNORE) -outputdir tmp
+BASEFLAGS=-Wall $(IGNORE) -outputdir tmp -IUtility
GHCFLAGS=-O2 $(BASEFLAGS)
ifdef PROFILE
@@ -11,7 +11,8 @@ GHCMAKE=ghc $(GHCFLAGS) --make
bins=git-annex
mans=git-annex.1 git-annex-shell.1
-sources=Build/SysConfig.hs Utility/StatFS.hs Utility/Touch.hs
+sources=Build/SysConfig.hs Utility/Touch.hs
+clibs=Utility/diskfree.o
all=$(bins) $(mans) docs
@@ -28,15 +29,16 @@ sources: $(sources)
fast: GHCFLAGS=$(BASEFLAGS)
fast: $(bins)
-Build/SysConfig.hs: configure.hs Build/TestConfig.hs Utility/StatFS.hs
+Build/SysConfig.hs: configure.hs Build/TestConfig.hs Build/Configure.hs
$(GHCMAKE) configure
./configure
%.hs: %.hsc
hsc2hs $<
-$(bins): $(sources)
- $(GHCMAKE) $@
+
+git-annex: $(sources) $(clibs)
+ $(GHCMAKE) $@ $(clibs)
git-annex.1: doc/git-annex.mdwn
./mdwn2man git-annex 1 doc/git-annex.mdwn > git-annex.1
@@ -92,7 +94,7 @@ docs: $(mans)
clean:
rm -rf tmp $(bins) $(mans) test configure *.tix .hpc $(sources) \
- doc/.ikiwiki html dist
+ doc/.ikiwiki html dist $(clibs)
# Workaround for cabal sdist not running Setup hooks, so I cannot
# generate a file list there.
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);
diff --git a/configure.hs b/configure.hs
index 6fdc5fcb0..15833e62a 100644
--- a/configure.hs
+++ b/configure.hs
@@ -1,23 +1,6 @@
{- configure program -}
-import Data.Maybe
-
-import qualified Build.Configure as Configure
-import Build.TestConfig
-import Utility.StatFS
-
-tests :: [TestCase]
-tests = [ TestCase "StatFS" testStatFS
- ] ++ Configure.tests False
-
-{- This test cannot be included in Build.Configure due to needing
- - Utility/StatFS.hs to be built, which it is not when "cabal configure"
- - is run. -}
-testStatFS :: Test
-testStatFS = do
- s <- getFileSystemStats "."
- return $ Config "statfs_sanity_checked" $
- MaybeBoolConfig $ Just $ isJust s
+import Build.Configure
main :: IO ()
-main = Configure.run tests
+main = run tests
diff --git a/debian/changelog b/debian/changelog
index fe91ee4e9..66e7b83a7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,7 @@
git-annex (3.20120316) UNRELEASED; urgency=low
- * Improve detection of inability to check free disk space.
- * status: Prints available local disk space, or shows if git-annex
- doesn't know.
+ * Rewrote free disk space checking code, moving the portability
+ handling into a small C library.
-- Joey Hess <joeyh@debian.org> Wed, 21 Mar 2012 21:19:16 -0400
diff --git a/debian/copyright b/debian/copyright
index 85fd174fc..332c1e71d 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -7,33 +7,3 @@ License: GPL-3+
The full text of version 3 of the GPL is distributed as doc/GPL in
this package's source, or in /usr/share/common-licenses/GPL-3 on
Debian systems.
-
-Files: Utility/StatFS.hsc
-Copyright: Jose A Ortega Ruiz <jao@gnu.org>
-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.
diff --git a/git-annex.cabal b/git-annex.cabal
index 881e4d212..184f6323a 100644
--- a/git-annex.cabal
+++ b/git-annex.cabal
@@ -1,5 +1,5 @@
Name: git-annex
-Version: 3.20120315
+Version: 3.20120316
Cabal-Version: >= 1.6
License: GPL
Maintainer: Joey Hess <joey@kitenet.net>