{-# LANGUAGE CPP #-} -- GIMP Toolkit (GTK) Binding for Haskell: binding to libgnomevfs -*-haskell-*- -- -- Author : Peter Gavin -- Created: 1-Apr-2007 -- -- Copyright (c) 2007 Peter Gavin -- -- This library is free software: you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public License -- as published by the Free Software Foundation, either version 3 of -- the License, or (at your option) any later version. -- -- This library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with this program. If not, see -- . -- -- GnomeVFS, the C library which this Haskell library depends on, is -- available under LGPL Version 2. The documentation included with -- this library is based on the original GnomeVFS documentation, -- Copyright (c) 2001 Seth Nickell . The -- documentation is covered by the GNU Free Documentation License, -- version 1.2. -- -- | Maintainer : gtk2hs-devel@lists.sourceforge.net -- Stability : alpha -- Portability : portable (depends on GHC) module System.Gnome.VFS.Ops ( -- * Types Handle, Result(..), OpenMode(..), SeekPosition(..), FilePermissions(..), FileSize, FileOffset, -- * I\/O Operations open, openURI, create, createURI, close, #if __GLASGOW_HASKELL__ >= 606 read, write, #endif seek, tell, #if GNOME_VFS_CHECK_VERSION(2,12,0) forgetCache, #endif -- * Truncation truncate, truncateURI, truncateHandle, -- * File Information getFileInfo, getFileInfoURI, getFileInfoFromHandle, setFileInfo, setFileInfoURI ) where #if __GLASGOW_HASKELL__ >= 606 && __GLASGOW_HASKELL__ < 608 #define OLD_BYTESTRING #endif import Control.Exception import Control.Monad (liftM) #if __GLASGOW_HASKELL__ >= 606 import qualified Data.ByteString as BS (ByteString, useAsCStringLen) #ifdef OLD_BYTESTRING import qualified Data.ByteString.Base as BS (fromForeignPtr) #else import qualified Data.ByteString.Internal as BS (fromForeignPtr) #endif #endif import Prelude hiding (read, truncate) import System.Glib.FFI import System.Glib.UTFString (withUTFString, peekUTFString) -- {#import System.Gnome.VFS.Types#} {#import System.Gnome.VFS.BasicTypes#} {#import System.Gnome.VFS.FileInfo#} {#import System.Gnome.VFS.Marshal#} {# context lib = "gnomevfs" prefix = "gnome_vfs" #} -- | Open the file at @textURI@. open :: TextURI -- ^ @textURI@ - -> OpenMode -- ^ @openMode@ - -> IO Handle -- ^ a handle to the opened file open textURI openMode = let cOpenMode = cFromEnum openMode in withUTFString textURI $ \cTextURI -> newObjectResultMarshal Handle $ \cHandlePtr -> {# call gnome_vfs_open #} (castPtr cHandlePtr) cTextURI cOpenMode -- | Open the file at @uri@. openURI :: URI -- ^ @uri@ - -> OpenMode -- ^ @openMode@ - -> IO Handle -- ^ a handle to the opened file openURI uri openMode = let cOpenMode = cFromEnum openMode in newObjectResultMarshal Handle $ \cHandlePtr -> {# call open_uri #} (castPtr cHandlePtr) uri cOpenMode -- | Create a file at @textURI@. create :: TextURI -- ^ @textURI@ - -> OpenMode -- ^ @openMode@ - -> Bool -- ^ @exclusive@ - -> [FilePermissions] -- ^ @perm@ - -> IO Handle -- ^ a handle to the created file create textURI openMode exclusive perm = let cOpenMode = cFromEnum openMode cExclusive = fromBool exclusive cPerm = cFromFlags perm in withUTFString textURI $ \cTextURI -> newObjectResultMarshal Handle $ \cHandlePtr -> {# call gnome_vfs_create #} (castPtr cHandlePtr) cTextURI cOpenMode cExclusive cPerm -- | Create a file at @uri@. createURI :: URI -- ^ @uri@ - -> OpenMode -- ^ @openMode@ - -> Bool -- ^ @exclusive@ - -> [FilePermissions] -- ^ @perm@ - -> IO Handle -- ^ a handle to the created file createURI uri openMode exclusive perm = let cOpenMode = cFromEnum openMode cExclusive = fromBool exclusive cPerm = cFromFlags perm in newObjectResultMarshal Handle $ \cHandlePtr -> {# call create_uri #} (castPtr cHandlePtr) uri cOpenMode cExclusive cPerm -- | Close a 'Handle'. close :: Handle -- ^ @handle@ - -> IO () close handle = voidResultMarshal $ {# call gnome_vfs_close #} handle #if __GLASGOW_HASKELL__ >= 606 -- | Read data from a file. read :: Handle -- ^ @handle@ - -> FileSize -- ^ @bytes@ - -> IO BS.ByteString -- ^ the data read from the file read handle bytes = let cBytes = fromIntegral bytes in do buffer <- mallocForeignPtrBytes $ fromIntegral bytes withForeignPtr buffer $ \cBuffer -> alloca $ \cBytesReadPtr -> genericResultMarshal (do poke cBytesReadPtr 0 {# call gnome_vfs_read #} handle cBuffer cBytes cBytesReadPtr) (do bytesRead <- liftM fromIntegral $ peek cBytesReadPtr assert (bytesRead /= 0 || cBytes == 0) $ return () return $ BS.fromForeignPtr (castForeignPtr buffer) #ifndef OLD_BYTESTRING 0 #endif (fromIntegral bytes)) (do bytesRead <- liftM fromIntegral $ peek cBytesReadPtr assert (bytesRead == 0) $ return ()) -- | Write data to a file. write :: Handle -- ^ @handle@ - -> BS.ByteString -- ^ @byteString@ - -> IO FileSize -- ^ the number of bytes actually written write handle byteString = BS.useAsCStringLen byteString $ \(cBuffer, bytes) -> let cBytes = fromIntegral bytes in alloca $ \cBytesWrittenPtr -> genericResultMarshal (do poke cBytesWrittenPtr 0 {# call gnome_vfs_write #} handle (castPtr cBuffer) cBytes cBytesWrittenPtr) (do bytesWritten <- liftM fromIntegral $ peek cBytesWrittenPtr assert (bytesWritten /= 0 || cBytes == 0) $ return () return bytesWritten) (do bytesWritten <- liftM fromIntegral $ peek cBytesWrittenPtr assert (bytesWritten == 0) $ return ()) #endif -- | Seek to a position in a file. seek :: Handle -- ^ @handle@ - -> SeekPosition -- ^ @whence@ - -> FileOffset -- ^ @offset@ - -> IO () seek handle whence offset = let cWhence = cFromEnum whence cOffset = fromIntegral offset in voidResultMarshal $ {# call gnome_vfs_seek #} handle cWhence cOffset -- | Return the current position in the file. tell :: Handle -- ^ @handle@ - -> IO FileSize -- ^ the current position in the file tell handle = alloca $ \cOffsetReturnPtr -> genericResultMarshal (do poke cOffsetReturnPtr 0 {# call gnome_vfs_tell #} handle cOffsetReturnPtr) (liftM fromIntegral $ peek cOffsetReturnPtr) (do cOffsetReturn <- peek cOffsetReturnPtr assert (cOffsetReturn == 0) $ return ()) #if GNOME_VFS_CHECK_VERSION(2,12,0) -- | Free any cache associated with the file opened on @handle@, -- in the region of @size@ bytes starting at @offset@. forgetCache :: Handle -> FileOffset -> FileSize -> IO () forgetCache handle offset size = let cOffset = fromIntegral offset cSize = fromIntegral size in voidResultMarshal $ {# call forget_cache #} handle cOffset cSize #endif -- | Truncate the file at @textURI@ to @length@ bytes. truncate :: String -> FileSize -> IO () truncate textURI length = let cLength = fromIntegral length in withUTFString textURI $ \cTextURI -> voidResultMarshal $ {# call gnome_vfs_truncate #} cTextURI cLength -- | Truncate the file at @uri@ to @length@ bytes. truncateURI :: URI -> FileSize -> IO () truncateURI uri length = let cLength = fromIntegral length in voidResultMarshal $ {# call truncate_uri #} uri cLength -- | Truncate the file opened on @handle@ to @length@ bytes. truncateHandle :: Handle -> FileSize -> IO () truncateHandle handle length = let cLength = fromIntegral length in voidResultMarshal $ {# call truncate_handle #} handle cLength -- | Get the file information for the file at @textURI@. getFileInfo :: String -> [FileInfoOptions] -> IO FileInfo getFileInfo textURI options = let cOptions = cFromFlags options in withUTFString textURI $ \cTextURI -> bracket {# call file_info_new #} {# call file_info_unref #} (\cFileInfo -> genericResultMarshal ({# call get_file_info #} cTextURI cFileInfo cOptions) (peek $ castPtr cFileInfo) (return ())) -- | Get the file information for the file at @uri@. getFileInfoURI :: URI -> [FileInfoOptions] -> IO FileInfo getFileInfoURI uri options = let cOptions = cFromFlags options in bracket {# call file_info_new #} {# call file_info_unref #} (\cFileInfo -> genericResultMarshal ({# call get_file_info_uri #} uri cFileInfo cOptions) (peek $ castPtr cFileInfo) (return ())) -- | Get the file information for the file opened on @handle@. getFileInfoFromHandle :: Handle -> [FileInfoOptions] -> IO FileInfo getFileInfoFromHandle handle options = let cOptions = cFromFlags options in bracket {# call file_info_new #} {# call file_info_unref #} (\cFileInfo -> genericResultMarshal ({# call get_file_info_from_handle #} handle cFileInfo cOptions) (peek $ castPtr cFileInfo) (return ())) -- | Set the file information for the file at @textURI@. setFileInfo :: String -> FileInfo -> [SetFileInfoMask] -> IO () setFileInfo textURI info mask = withUTFString textURI $ \cTextURI -> with info $ \cInfo -> voidResultMarshal $ {# call set_file_info #} cTextURI (castPtr cInfo) $ cFromFlags mask -- | Set the file information for the file at @uri@. setFileInfoURI :: URI -> FileInfo -> [SetFileInfoMask] -> IO () setFileInfoURI uri info mask = with info $ \cInfo -> voidResultMarshal $ {# call set_file_info_uri #} uri (castPtr cInfo) $ cFromFlags mask