Skip to content

Commit

Permalink
Add statx
Browse files Browse the repository at this point in the history
  • Loading branch information
hasufell committed Sep 16, 2023
1 parent 3f0d217 commit 1115a92
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
9 changes: 9 additions & 0 deletions System/Posix/Files.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ module System.Posix.Files (
fileBlockSize,
fileBlocks,

-- * Extended file status
StatxFlags(..),
defaultStatxFlags,
StatxMask(..),
defaultStatxMask,
ExtendedFileStatus(..),
fileSizeX,
fileGroupX,

-- * Creation
createNamedPipe,
createDevice,
Expand Down
17 changes: 17 additions & 0 deletions System/Posix/Files/ByteString.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,14 @@ module System.Posix.Files.ByteString (

-- * File status
FileStatus,
StatxFlags(..),
defaultStatxFlags,
StatxMask(..),
defaultStatxMask,
ExtendedFileStatus(..),
-- ** Obtaining file status
getFileStatus, getFdStatus, getSymbolicLinkStatus,
getExtendedFileStatus,
-- ** Querying file status
deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
specialDeviceID, fileSize, accessTime, modificationTime,
Expand Down Expand Up @@ -184,6 +190,17 @@ getFileStatus path = do
throwErrnoPathIfMinus1Retry_ "getFileStatus" path (c_stat s p)
return (FileStatus fp)

-- | @getExtendedFileStatus path@ gets the @FileStatus@ information (user ID,
-- size, access times, etc.) for the file @path@.
--
-- Note: calls @statx@.
getExtendedFileStatus :: Maybe Fd -- ^ Optional directory file descriptor
-> RawFilePath -- ^ Pathname to open
-> StatxFlags
-> StatxMask
-> IO ExtendedFileStatus
getExtendedFileStatus mfd path flags masks = withFilePath path $ \s -> getExtendedFileStatus_ mfd s flags masks

-- | Acts as 'getFileStatus' except when the 'RawFilePath' refers to a symbolic
-- link. In that case the @FileStatus@ information of the symbolic link itself
-- is returned instead of that of the file it points to.
Expand Down
118 changes: 118 additions & 0 deletions System/Posix/Files/Common.hsc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE Trustworthy #-}

-----------------------------------------------------------------------------
Expand Down Expand Up @@ -60,6 +61,17 @@ module System.Posix.Files.Common (
fileBlockSize,
fileBlocks,

-- * Extended file status
StatxFlags(..),
defaultStatxFlags,
StatxMask(..),
defaultStatxMask,
ExtendedFileStatus(..),
getExtendedFileStatus_,
fileSizeX,
fileGroupX,
fileOwnerX,

-- * Setting file sizes
setFdSize,

Expand Down Expand Up @@ -688,3 +700,109 @@ getFdPathVar (Fd fd) v =

foreign import ccall unsafe "fpathconf"
c_fpathconf :: CInt -> CInt -> IO CLong


-- -----------------------------------------------------------------------------
-- statx
--
data StatxFlags =
StatxFlags {
emptyPath :: Bool
, noAutoMount :: Bool
, symlinkNoFollow :: Bool
}
deriving (Read, Show, Eq, Ord)


defaultStatxFlags :: StatxFlags
defaultStatxFlags =
StatxFlags {
emptyPath = False,
noAutoMount = False,
symlinkNoFollow = False
}

data StatxMask =
StatxMask {
statx_type :: Bool
, statx_mode :: Bool
, statx_nlink :: Bool
, statx_uid :: Bool
, statx_gid :: Bool
, statx_atime :: Bool
, statx_mtime :: Bool
, statx_ctime :: Bool
, statx_ino :: Bool
, statx_size :: Bool
, statx_blocks :: Bool
, statx_btime :: Bool
}
deriving (Read, Show, Eq, Ord)


defaultStatxMask :: StatxMask
defaultStatxMask =
StatxMask {
statx_type = False
, statx_mode = False
, statx_nlink = False
, statx_uid = False
, statx_gid = False
, statx_atime = False
, statx_mtime = False
, statx_ctime = False
, statx_ino = False
, statx_size = False
, statx_blocks = False
, statx_btime = False
}

newtype ExtendedFileStatus = ExtendedFileStatus (ForeignPtr CStatx) -- ^ The constructor is considered internal and may change.

fileOwnerX :: ExtendedFileStatus -> UserID
fileGroupX :: ExtendedFileStatus -> GroupID
fileSizeX :: ExtendedFileStatus -> FileOffset

fileOwnerX (ExtendedFileStatus statx) =
unsafePerformIO $ withForeignPtr statx $ (#peek struct statx, stx_uid)
fileGroupX (ExtendedFileStatus statx) =
unsafePerformIO $ withForeignPtr statx $ (#peek struct statx, stx_gid)
fileSizeX (ExtendedFileStatus statx) =
unsafePerformIO $ withForeignPtr statx $ (#peek struct statx, stx_size)

data {-# CTYPE "struct statx" #-} CStatx

foreign import ccall unsafe "statx"
c_statx :: CInt -> CFilePath -> CInt -> CInt -> Ptr CStatx -> IO CInt


getExtendedFileStatus_ :: Maybe Fd -- ^ Optional directory file descriptor
-> CString -- ^ Pathname to open
-> StatxFlags
-> StatxMask
-> IO ExtendedFileStatus
getExtendedFileStatus_ fdMay str StatxFlags{..} StatxMask{..} = do
fp <- mallocForeignPtrBytes (#const sizeof(struct statx))
withForeignPtr fp $ \p ->
throwErrnoIfMinus1Retry_ "getExtendedFileStatus_" (c_statx c_fd str flags masks p)
return (ExtendedFileStatus fp)
where
c_fd = maybe (#const AT_FDCWD) (\ (Fd fd) -> fd) fdMay
flags =
(if emptyPath then (#const AT_EMPTY_PATH) else 0) .|.
(if noAutoMount then (#const AT_NO_AUTOMOUNT) else 0) .|.
(if symlinkNoFollow then (#const AT_SYMLINK_NOFOLLOW) else 0)
masks =
(if statx_type then (#const STATX_TYPE) else 0) .|.
(if statx_mode then (#const STATX_MODE) else 0) .|.
(if statx_nlink then (#const STATX_NLINK) else 0) .|.
(if statx_uid then (#const STATX_UID) else 0) .|.
(if statx_gid then (#const STATX_GID) else 0) .|.
(if statx_atime then (#const STATX_ATIME) else 0) .|.
(if statx_mtime then (#const STATX_MTIME) else 0) .|.
(if statx_ctime then (#const STATX_CTIME) else 0) .|.
(if statx_ino then (#const STATX_INO) else 0) .|.
(if statx_size then (#const STATX_SIZE) else 0) .|.
(if statx_blocks then (#const STATX_BLOCKS) else 0) .|.
(if statx_btime then (#const STATX_BTIME) else 0)

5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ AC_CHECK_FUNCS([chown fchdir fchmod])

AC_CHECK_TYPE([struct rlimit],[AC_DEFINE([HAVE_STRUCT_RLIMIT],[1],[HAVE_STRUCT_RLIMIT])],[],[#include <sys/resource.h>])

# check for statx
AC_CHECK_FUNC([statx], [AC_DEFINE([HAVE_STATX_FUN],[1],[HAVE_STATX_FUN])],[],[#include <sys/stat.h>])
AC_CHECK_TYPE([struct statx],[AC_DEFINE([HAVE_STRUCT_STATX],[1],[HAVE_STRUCT_STATX])],[],[#include <sys/stat.h>])
AS_IF([test "x$HAVE_STRUCT_STATX" = "x1" && test "x$HAVE_STATX_FUN" = "x1"], [AC_DEFINE([HAVE_STATX],[1],[HAVE_STATX])])

AC_MSG_CHECKING(for F_GETLK from fcntl.h)
AC_EGREP_CPP(yes,
[
Expand Down

0 comments on commit 1115a92

Please sign in to comment.