unix 2.3.2.0 → 2.4.0.0
raw patch · 18 files changed
+534/−134 lines, 18 filesdep ~base
Dependency ranges changed: base
Files
- System/Posix/Directory.hsc +25/−5
- System/Posix/IO.hsc +101/−11
- System/Posix/Process.hsc +4/−4
- System/Posix/Process/Internals.hs +0/−2
- System/Posix/Semaphore.hsc +5/−9
- System/Posix/Signals.hsc +9/−4
- System/Posix/Terminal.hsc +2/−1
- System/Posix/Time.hsc +1/−1
- System/Posix/Unistd.hsc +1/−1
- System/Posix/User.hsc +59/−45
- cbits/HsUnix.c +52/−0
- cbits/dirUtils.c +83/−0
- configure +106/−12
- configure.ac +9/−8
- include/HsUnix.h +31/−0
- include/HsUnixConfig.h +3/−0
- include/HsUnixConfig.h.in +3/−0
- unix.cabal +40/−31
System/Posix/Directory.hsc view
@@ -37,8 +37,6 @@ import System.IO.Error import System.Posix.Error import System.Posix.Types-import System.Posix.Internals---import System.Directory hiding (createDirectory) import Foreign import Foreign.C @@ -63,6 +61,9 @@ dirp <- throwErrnoPathIfNull "openDirStream" name $ c_opendir s return (DirStream dirp) +foreign import ccall unsafe "__hsunix_opendir"+ c_opendir :: CString -> IO (Ptr CDir)+ -- | @readDirStream dp@ calls @readdir@ to obtain the -- next directory entry (@struct dirent@) for the open directory -- stream @dp@, and returns the @d_name@ member of that@@ -73,32 +74,51 @@ where loop ptr_dEnt = do resetErrno- r <- readdir dirp ptr_dEnt+ r <- c_readdir dirp ptr_dEnt if (r == 0) then do dEnt <- peek ptr_dEnt if (dEnt == nullPtr) then return [] else do entry <- (d_name dEnt >>= peekCString)- freeDirEnt dEnt+ c_freeDirEnt dEnt return entry else do errno <- getErrno if (errno == eINTR) then loop ptr_dEnt else do let (Errno eo) = errno- if (eo == end_of_dir)+ if (eo == 0) then return [] else throwErrno "readDirStream" +type CDir = ()+type CDirent = ()++-- traversing directories+foreign import ccall unsafe "__hscore_readdir"+ c_readdir :: Ptr CDir -> Ptr (Ptr CDirent) -> IO CInt++foreign import ccall unsafe "__hscore_free_dirent"+ c_freeDirEnt :: Ptr CDirent -> IO ()++foreign import ccall unsafe "__hscore_d_name"+ d_name :: Ptr CDirent -> IO CString+ -- | @rewindDirStream dp@ calls @rewinddir@ to reposition -- the directory stream @dp@ at the beginning of the directory. rewindDirStream :: DirStream -> IO () rewindDirStream (DirStream dirp) = c_rewinddir dirp +foreign import ccall unsafe "rewinddir"+ c_rewinddir :: Ptr CDir -> IO ()+ -- | @closeDirStream dp@ calls @closedir@ to close -- the directory stream @dp@. closeDirStream :: DirStream -> IO () closeDirStream (DirStream dirp) = do throwErrnoIfMinus1_ "closeDirStream" (c_closedir dirp)++foreign import ccall unsafe "closedir"+ c_closedir :: Ptr CDir -> IO CInt newtype DirStreamOffset = DirStreamOffset COff
System/Posix/IO.hsc view
@@ -1,5 +1,6 @@ {-# LANGUAGE ForeignFunctionInterface #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-}+{-# OPTIONS_GHC -XRecordWildCards #-} ----------------------------------------------------------------------------- -- | -- Module : System.Posix.IO@@ -34,6 +35,7 @@ -- EAGAIN exceptions may occur for non-blocking IO! fdRead, fdWrite,+ fdReadBuf, fdWriteBuf, -- ** Seeking fdSeek,@@ -65,17 +67,27 @@ import System.IO.Error import System.Posix.Types import System.Posix.Error-import System.Posix.Internals+import qualified System.Posix.Internals as Base import Foreign import Foreign.C import Data.Bits #ifdef __GLASGOW_HASKELL__+#if __GLASGOW_HASKELL__ >= 611+import GHC.IO.Handle+import GHC.IO.Handle.Internals+import GHC.IO.Handle.Types+import qualified GHC.IO.FD as FD+import qualified GHC.IO.Handle.FD as FD+import GHC.IO.Exception+import Data.Typeable (cast)+#else import GHC.IOBase import GHC.Handle hiding (fdToHandle) import qualified GHC.Handle #endif+#endif #ifdef __HUGS__ import Hugs.Prelude (IOException(..), IOErrorType(..))@@ -101,6 +113,9 @@ wfd <- peekElemOff p_fd 1 return (Fd rfd, Fd wfd) +foreign import ccall unsafe "pipe"+ c_pipe :: Ptr CInt -> IO CInt+ -- ----------------------------------------------------------------------------- -- Duplicating file descriptors @@ -114,6 +129,12 @@ r <- throwErrnoIfMinus1 "dupTo" (c_dup2 fd1 fd2) return (Fd r) +foreign import ccall unsafe "dup"+ c_dup :: CInt -> IO CInt++foreign import ccall unsafe "dup2"+ c_dup2 :: CInt -> CInt -> IO CInt+ -- ----------------------------------------------------------------------------- -- Opening and closing files @@ -179,6 +200,9 @@ WriteOnly -> (#const O_WRONLY) ReadWrite -> (#const O_RDWR) +foreign import ccall unsafe "__hscore_open"+ c_open :: CString -> CInt -> CMode -> IO CInt+ -- |Create and open this file in WriteOnly mode. A special case of -- 'openFd'. See 'System.Posix.Files' for information on how to use -- the 'FileMode' type.@@ -193,6 +217,9 @@ closeFd :: Fd -> IO () closeFd (Fd fd) = throwErrnoIfMinus1_ "closeFd" (c_close fd) +foreign import ccall unsafe "HsBase.h close"+ c_close :: CInt -> IO CInt+ -- ----------------------------------------------------------------------------- -- Converting file descriptors to/from Handles @@ -210,6 +237,24 @@ fdToHandle :: Fd -> IO Handle #ifdef __GLASGOW_HASKELL__+#if __GLASGOW_HASKELL__ >= 611+handleToFd h = withHandle "handleToFd" h $ \ h_@Handle__{haType=_,..} -> do+ case cast haDevice of+ Nothing -> ioError (ioeSetErrorString (mkIOError IllegalOperation+ "handleToFd" (Just h) Nothing) + "handle is not a file descriptor")+ Just fd -> do+ -- converting a Handle into an Fd effectively means+ -- letting go of the Handle; it is put into a closed+ -- state as a result. + flushWriteBuffer h_+ FD.release fd+ return (Handle__{haType=ClosedHandle,..}, Fd (fromIntegral (FD.fdFD fd)))++fdToHandle fd = FD.fdToHandle (fromIntegral fd)++#else+ handleToFd h = withHandle "handleToFd" h $ \ h_ -> do -- converting a Handle into an Fd effectively means -- letting go of the Handle; it is put into a closed@@ -224,6 +269,7 @@ fdToHandle fd = GHC.Handle.fdToHandle (fromIntegral fd) #endif+#endif #ifdef __HUGS__ handleToFd h = do@@ -273,6 +319,12 @@ _ -> ((#const F_GETFL),(#const F_SETFL)) opt_val = fdOption2Int opt +foreign import ccall unsafe "HsBase.h fcntl_read"+ c_fcntl_read :: CInt -> CInt -> IO CInt++foreign import ccall unsafe "HsBase.h fcntl_write"+ c_fcntl_write :: CInt -> CInt -> CLong -> IO CInt+ -- ----------------------------------------------------------------------------- -- Seeking @@ -284,7 +336,7 @@ -- | May throw an exception if this is an invalid descriptor. fdSeek :: Fd -> SeekMode -> FileOffset -> IO FileOffset fdSeek (Fd fd) mode off =- throwErrnoIfMinus1 "fdSeek" (c_lseek fd off (mode2Int mode))+ throwErrnoIfMinus1 "fdSeek" (Base.c_lseek fd off (mode2Int mode)) -- ----------------------------------------------------------------------------- -- Locking@@ -306,6 +358,11 @@ maybeResult (_, (Unlock, _, _, _)) = Nothing maybeResult x = Just x +type CFLock = ()++foreign import ccall unsafe "HsBase.h fcntl_lock"+ c_fcntl_lock :: CInt -> CInt -> Ptr CFLock -> IO CInt+ allocaLock :: FileLock -> (Ptr CFLock -> IO a) -> IO a allocaLock (lockreq, mode, start, len) io = allocaBytes (#const sizeof(struct flock)) $ \p -> do@@ -357,22 +414,55 @@ -- ----------------------------------------------------------------------------- -- fd{Read,Write} --- | May throw an exception if this is an invalid descriptor.+-- | Read data from an 'Fd' and convert it to a 'String'. Throws an+-- exception if this is an invalid descriptor, or EOF has been+-- reached. fdRead :: Fd -> ByteCount -- ^How many bytes to read -> IO (String, ByteCount) -- ^The bytes read, how many bytes were read. fdRead _fd 0 = return ("", 0)-fdRead (Fd fd) nbytes = do- allocaBytes (fromIntegral nbytes) $ \ bytes -> do- rc <- throwErrnoIfMinus1Retry "fdRead" (c_read fd bytes nbytes)+fdRead fd nbytes = do+ allocaBytes (fromIntegral nbytes) $ \ buf -> do+ rc <- fdReadBuf fd buf nbytes case fromIntegral rc of- 0 -> ioError (IOError Nothing EOF "fdRead" "EOF" Nothing)+ 0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF") n -> do- s <- peekCStringLen (bytes, fromIntegral n)+ s <- peekCStringLen (castPtr buf, fromIntegral n) return (s, n) --- | May throw an exception if this is an invalid descriptor.+-- | Read data from an 'Fd' into memory. This is exactly equivalent+-- to the POSIX @read@ function.+fdReadBuf :: Fd+ -> Ptr Word8 -- ^ Memory in which to put the data+ -> ByteCount -- ^ Maximum number of bytes to read+ -> IO ByteCount -- ^ Number of bytes read (zero for EOF)+fdReadBuf _fd _buf 0 = return 0+fdReadBuf fd buf nbytes = + fmap fromIntegral $+ throwErrnoIfMinus1Retry "fdReadBuf" $ + c_safe_read (fromIntegral fd) (castPtr buf) (fromIntegral nbytes)++foreign import ccall safe "read"+ c_safe_read :: CInt -> Ptr CChar -> CSize -> IO CSsize++-- | Write a 'String' to an 'Fd' (no character conversion is done,+-- the least-significant 8 bits of each character are written). fdWrite :: Fd -> String -> IO ByteCount-fdWrite (Fd fd) str = withCStringLen str $ \ (strPtr,len) -> do- rc <- throwErrnoIfMinus1Retry "fdWrite" (c_write fd strPtr (fromIntegral len))+fdWrite fd str = + withCStringLen str $ \ (buf,len) -> do+ rc <- fdWriteBuf fd (castPtr buf) (fromIntegral len) return (fromIntegral rc)++-- | Write data from memory to an 'Fd'. This is exactly equivalent+-- to the POSIX @write@ function.+fdWriteBuf :: Fd+ -> Ptr Word8 -- ^ Memory containing the data to write+ -> ByteCount -- ^ Maximum number of bytes to write+ -> IO ByteCount -- ^ Number of bytes written+fdWriteBuf fd buf len =+ fmap fromIntegral $+ throwErrnoIfMinus1Retry "fdWriteBuf" $ + c_safe_write (fromIntegral fd) (castPtr buf) (fromIntegral len)++foreign import ccall safe "write" + c_safe_write :: CInt -> Ptr CChar -> CSize -> IO CSsize
System/Posix/Process.hsc view
@@ -71,9 +71,7 @@ import Foreign.Ptr ( Ptr, nullPtr ) import Foreign.StablePtr ( StablePtr, newStablePtr, freeStablePtr ) import Foreign.Storable ( Storable(..) )-import System.IO import System.Exit-import System.Posix.Error import System.Posix.Process.Internals import System.Posix.Types import Control.Monad@@ -175,7 +173,7 @@ type CTms = () -foreign import ccall unsafe "times"+foreign import ccall unsafe "__hsunix_times" c_times :: Ptr CTms -> IO CClock -- -----------------------------------------------------------------------------@@ -276,7 +274,7 @@ -> Bool -- ^ Search PATH? -> [String] -- ^ Arguments -> Maybe [(String, String)] -- ^ Environment- -> IO ()+ -> IO a executeFile path search args Nothing = do withCString path $ \s -> withMany withCString (path:args) $ \cstrs ->@@ -285,6 +283,7 @@ if search then throwErrnoPathIfMinus1_ "executeFile" path (c_execvp s arr) else throwErrnoPathIfMinus1_ "executeFile" path (c_execv s arr)+ return undefined -- never reached executeFile path search args (Just env) = do withCString path $ \s ->@@ -299,6 +298,7 @@ (c_execvpe s arg_arr env_arr) else throwErrnoPathIfMinus1_ "executeFile" path (c_execve s arg_arr env_arr)+ return undefined -- never reached foreign import ccall unsafe "execvp" c_execvp :: CString -> Ptr CString -> IO CInt
System/Posix/Process/Internals.hs view
@@ -9,8 +9,6 @@ import System.IO.Error import GHC.Conc (Signal) --- we had to move this into GHC.Conc in GHC to avoid recursive dependencies.--- it can be moved back when the signal handling stuff in base is moved out. data ProcessStatus = Exited ExitCode | Terminated Signal | Stopped Signal
System/Posix/Semaphore.hsc view
@@ -24,12 +24,12 @@ #include <fcntl.h> import Foreign.C-import Foreign.ForeignPtr+import Foreign.ForeignPtr hiding (newForeignPtr)+import Foreign.Concurrent import Foreign.Marshal import Foreign.Ptr import Foreign.Storable import System.Posix.Types-import System.Posix.Error import Control.Concurrent import Data.Bits @@ -52,11 +52,10 @@ semOpen' cname = do sem <- throwErrnoPathIfNull "semOpen" name $ sem_open cname (toEnum cflags) mode (toEnum value)- finalizer <- mkCallback (finalize sem)- fptr <- newForeignPtr finalizer sem+ fptr <- newForeignPtr sem (finalize sem) return $ Semaphore fptr- finalize sem _ = throwErrnoPathIfMinus1_ "semOpen" name $- sem_close sem in+ finalize sem = throwErrnoPathIfMinus1_ "semOpen" name $+ sem_close sem in withCAString name semOpen' -- | Delete the semaphore with the given name.@@ -112,9 +111,6 @@ cint <- peek ptr return $ fromEnum cint -foreign import ccall safe "wrapper"- mkCallback :: (Ptr () -> IO ()) -> IO (FunPtr (Ptr () -> IO ()))- foreign import ccall safe "sem_open" sem_open :: CString -> CInt -> CMode -> CUInt -> IO (Ptr ()) foreign import ccall safe "sem_close"
System/Posix/Signals.hsc view
@@ -103,14 +103,17 @@ import Foreign.C import System.Posix.Types import System.Posix.Internals-import System.Posix.Process.Internals import System.Posix.Process-import Control.Monad+import System.Posix.Process.Internals import Data.Dynamic #ifdef __GLASGOW_HASKELL__+#if __GLASGOW_HASKELL__ >= 611+##include "rts/Signals.h"+#else ##include "Signals.h"-import GHC.IOBase+#endif+ import GHC.Conc hiding (Signal) #endif @@ -571,10 +574,12 @@ Nothing -> do SignalSet fp <- getSignalMask; return fp Just (SignalSet fp) -> return fp withForeignPtr fp $ \p -> do- c_sigsuspend p+ _ <- c_sigsuspend p return () -- ignore the return value; according to the docs it can only ever be -- (-1) with errno set to EINTR.+ -- XXX My manpage says it can also return EFAULT. And why is ignoring+ -- EINTR the right thing to do? foreign import ccall unsafe "sigsuspend" c_sigsuspend :: Ptr CSigset -> IO CInt
System/Posix/Terminal.hsc view
@@ -801,5 +801,6 @@ withForeignPtr fp1 $ \p1 -> do withTerminalAttributes termios $ \p2 -> do copyBytes p1 p2 (#const sizeof(struct termios))- action p1+ _ <- action p1+ return () return $ makeTerminalAttributes fp1
System/Posix/Time.hsc view
@@ -33,5 +33,5 @@ epochTime :: IO EpochTime epochTime = throwErrnoIfMinus1 "epochTime" (c_time nullPtr) -foreign import ccall unsafe "time"+foreign import ccall unsafe "__hsunix_time" c_time :: Ptr CTime -> IO CTime
System/Posix/Unistd.hsc view
@@ -158,7 +158,7 @@ data CTimeSpec -foreign import ccall safe "nanosleep" +foreign import ccall safe "__hsunix_nanosleep" c_nanosleep :: Ptr CTimeSpec -> Ptr CTimeSpec -> IO CInt #endif
System/Posix/User.hsc view
@@ -167,13 +167,13 @@ #ifdef HAVE_GETGRGID_R getGroupEntryForID gid = do allocaBytes (#const sizeof(struct group)) $ \pgr ->- allocaBytes grBufSize $ \pbuf ->- alloca $ \ ppgr -> do- throwErrorIfNonZero_ "getGroupEntryForID" $- c_getgrgid_r gid pgr pbuf (fromIntegral grBufSize) ppgr- throwErrnoIfNull "getGroupEntryForID" $- peekElemOff ppgr 0- unpackGroupEntry pgr+ alloca $ \ ppgr -> do+ throwErrorIfNonZero_ "getGroupEntryForID" $+ doubleAllocWhile isERANGE grBufSize $ \s b ->+ c_getgrgid_r gid pgr b (fromIntegral s) ppgr+ _ <- throwErrnoIfNull "getGroupEntryForID" $+ peekElemOff ppgr 0+ unpackGroupEntry pgr foreign import ccall unsafe "getgrgid_r"@@ -190,19 +190,19 @@ #ifdef HAVE_GETGRNAM_R getGroupEntryForName name = do allocaBytes (#const sizeof(struct group)) $ \pgr ->- allocaBytes grBufSize $ \pbuf ->- alloca $ \ ppgr ->- withCString name $ \ pstr -> do- throwErrorIfNonZero_ "getGroupEntryForName" $- c_getgrnam_r pstr pgr pbuf (fromIntegral grBufSize) ppgr- r <- peekElemOff ppgr 0- when (r == nullPtr) $- ioError $ flip ioeSetErrorString "no group name"- $ mkIOError doesNotExistErrorType- "getGroupEntryForName"- Nothing- (Just name)- unpackGroupEntry pgr+ alloca $ \ ppgr ->+ withCString name $ \ pstr -> do+ throwErrorIfNonZero_ "getGroupEntryForName" $+ doubleAllocWhile isERANGE grBufSize $ \s b ->+ c_getgrnam_r pstr pgr b (fromIntegral s) ppgr+ r <- peekElemOff ppgr 0+ when (r == nullPtr) $+ ioError $ flip ioeSetErrorString "no group name"+ $ mkIOError doesNotExistErrorType+ "getGroupEntryForName"+ Nothing+ (Just name)+ unpackGroupEntry pgr foreign import ccall unsafe "getgrnam_r" c_getgrnam_r :: CString -> Ptr CGroup -> CString@@ -213,6 +213,12 @@ -- | @getAllGroupEntries@ returns all group entries on the system by -- repeatedly calling @getgrent@++--+-- getAllGroupEntries may fail with isDoesNotExistError on Linux due to+-- this bug in glibc:+-- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=466647+-- getAllGroupEntries :: IO [GroupEntry] #ifdef HAVE_GETGRENT getAllGroupEntries =@@ -235,9 +241,9 @@ #if defined(HAVE_GETGRGID_R) || defined(HAVE_GETGRNAM_R) grBufSize :: Int #if defined(HAVE_SYSCONF) && defined(HAVE_SC_GETGR_R_SIZE_MAX)-grBufSize = sysconfWithDefault 2048 (#const _SC_GETGR_R_SIZE_MAX)+grBufSize = sysconfWithDefault 1024 (#const _SC_GETGR_R_SIZE_MAX) #else-grBufSize = 2048 -- just assume some value (1024 is too small on OpenBSD)+grBufSize = 1024 #endif #endif @@ -284,15 +290,15 @@ #ifdef HAVE_GETPWUID_R getUserEntryForID uid = do allocaBytes (#const sizeof(struct passwd)) $ \ppw ->- allocaBytes pwBufSize $ \pbuf ->- alloca $ \ pppw -> do- throwErrorIfNonZero_ "getUserEntryForID" $- c_getpwuid_r uid ppw pbuf (fromIntegral pwBufSize) pppw- throwErrnoIfNull "getUserEntryForID" $- peekElemOff pppw 0- unpackUserEntry ppw+ alloca $ \ pppw -> do+ throwErrorIfNonZero_ "getUserEntryForID" $+ doubleAllocWhile isERANGE pwBufSize $ \s b ->+ c_getpwuid_r uid ppw b (fromIntegral s) pppw+ _ <- throwErrnoIfNull "getUserEntryForID" $+ peekElemOff pppw 0+ unpackUserEntry ppw -foreign import ccall unsafe "getpwuid_r"+foreign import ccall unsafe "__hsunix_getpwuid_r" c_getpwuid_r :: CUid -> Ptr CPasswd -> CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt #elif HAVE_GETPWUID@@ -314,21 +320,21 @@ #if HAVE_GETPWNAM_R getUserEntryForName name = do allocaBytes (#const sizeof(struct passwd)) $ \ppw ->- allocaBytes pwBufSize $ \pbuf ->- alloca $ \ pppw ->- withCString name $ \ pstr -> do- throwErrorIfNonZero_ "getUserEntryForName" $- c_getpwnam_r pstr ppw pbuf (fromIntegral pwBufSize) pppw- r <- peekElemOff pppw 0- when (r == nullPtr) $- ioError $ flip ioeSetErrorString "no user name"- $ mkIOError doesNotExistErrorType- "getUserEntryForName"- Nothing- (Just name)- unpackUserEntry ppw+ alloca $ \ pppw ->+ withCString name $ \ pstr -> do+ throwErrorIfNonZero_ "getUserEntryForName" $+ doubleAllocWhile isERANGE pwBufSize $ \s b ->+ c_getpwnam_r pstr ppw b (fromIntegral s) pppw+ r <- peekElemOff pppw 0+ when (r == nullPtr) $+ ioError $ flip ioeSetErrorString "no user name"+ $ mkIOError doesNotExistErrorType+ "getUserEntryForName"+ Nothing+ (Just name)+ unpackUserEntry ppw -foreign import ccall unsafe "getpwnam_r"+foreign import ccall unsafe "__hsunix_getpwnam_r" c_getpwnam_r :: CString -> Ptr CPasswd -> CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt #elif HAVE_GETPWNAM@@ -359,7 +365,7 @@ else do thisentry <- unpackUserEntry ppw worker (thisentry : accum) -foreign import ccall unsafe "getpwent"+foreign import ccall unsafe "__hsunix_getpwent" c_getpwent :: IO (Ptr CPasswd) foreign import ccall unsafe "setpwent" c_setpwent :: IO ()@@ -391,6 +397,14 @@ unsafePerformIO $ do v <- fmap fromIntegral $ c_sysconf sc return $ if v == (-1) then def else v #endif++isERANGE :: Integral a => a -> Bool+isERANGE = (== eRANGE) . Errno . fromIntegral++doubleAllocWhile :: (a -> Bool) -> Int -> (Int -> Ptr b -> IO a) -> IO a+doubleAllocWhile p s m = do+ r <- allocaBytes s (m s)+ if p r then doubleAllocWhile p (2 * s) m else return r unpackUserEntry :: Ptr CPasswd -> IO UserEntry unpackUserEntry ptr = do
cbits/HsUnix.c view
@@ -42,6 +42,58 @@ return mknod(pathname,mode,dev); } +#ifdef HAVE_GETPWENT+// getpwent is a macro on some platforms, so we need a wrapper:+struct passwd *__hsunix_getpwent(void)+{+ return getpwent();+}+#endif++#if HAVE_GETPWNAM_R+// getpwnam_r is a macro on some platforms, so we need a wrapper:+int __hsunix_getpwnam_r(const char *name, struct passwd *pw, char *buffer,+ size_t buflen, struct passwd **result)+{+ return getpwnam_r(name, pw, buffer, buflen, result);+}+#endif++#ifdef HAVE_GETPWUID_R+// getpwuid_r is a macro on some platforms, so we need a wrapper:+int __hsunix_getpwuid_r(uid_t uid, struct passwd *pw, char *buffer,+ size_t buflen, struct passwd **result)+{+ return getpwuid_r(uid, pw, buffer, buflen, result);+}+#endif++#ifdef HAVE_NANOSLEEP+// nanosleep is a macro on some platforms, so we need a wrapper:+int __hsunix_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)+{+ return nanosleep(rqtp, rmtp);+}+#endif++// opendir is a macro on some platforms, so we need a wrapper:+DIR *__hsunix_opendir(const char *filename)+{+ return opendir(filename);+}++// time is a macro on some platforms, so we need a wrapper:+time_t __hsunix_time(time_t *tloc)+{+ return time(tloc);+}++// times is a macro on some platforms, so we need a wrapper:+clock_t __hsunix_times(struct tms *tp)+{+ return times(tp);+}+ #ifdef HAVE_PTSNAME // I cannot figure out how to make the definitions of the following // functions visible in <stdlib.h> on Linux. But these definitions
+ cbits/dirUtils.c view
@@ -0,0 +1,83 @@+/* + * (c) The University of Glasgow 2002+ *+ * Directory Runtime Support+ */++/* needed only for solaris2_HOST_OS */+#ifdef __GLASGOW_HASKELL__+#include "ghcconfig.h"+#endif++// The following is required on Solaris to force the POSIX versions of+// the various _r functions instead of the Solaris versions.+#ifdef solaris2_HOST_OS+#define _POSIX_PTHREAD_SEMANTICS+#endif++#include "HsUnix.h"++/*+ * read an entry from the directory stream; opt for the+ * re-entrant friendly way of doing this, if available.+ */+int+__hscore_readdir( DIR *dirPtr, struct dirent **pDirEnt )+{+#if HAVE_READDIR_R+ struct dirent* p;+ int res;+ static unsigned int nm_max = (unsigned int)-1;+ + if (pDirEnt == NULL) {+ return -1;+ }+ if (nm_max == (unsigned int)-1) {+#ifdef NAME_MAX+ nm_max = NAME_MAX + 1;+#else+ nm_max = pathconf(".", _PC_NAME_MAX);+ if (nm_max == -1) { nm_max = 255; }+ nm_max++;+#endif+ }+ p = (struct dirent*)malloc(sizeof(struct dirent) + nm_max);+ if (p == NULL) return -1;+ res = readdir_r(dirPtr, p, pDirEnt);+ if (res != 0) {+ *pDirEnt = NULL;+ free(p);+ }+ else if (*pDirEnt == NULL) {+ // end of stream+ free(p);+ }+ return res;+#else++ if (pDirEnt == NULL) {+ return -1;+ }++ *pDirEnt = readdir(dirPtr);+ if (*pDirEnt == NULL) {+ return -1;+ } else {+ return 0;+ } +#endif+}++char *+__hscore_d_name( struct dirent* d )+{+ return (d->d_name);+}++void+__hscore_free_dirent(struct dirent *dEnt)+{+#if HAVE_READDIR_R+ free(dEnt);+#endif+}
configure view
@@ -5185,6 +5185,100 @@ done +for ac_func in readdir_r+do+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`+{ echo "$as_me:$LINENO: checking for $ac_func" >&5+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then+ echo $ECHO_N "(cached) $ECHO_C" >&6+else+ cat >conftest.$ac_ext <<_ACEOF+/* confdefs.h. */+_ACEOF+cat confdefs.h >>conftest.$ac_ext+cat >>conftest.$ac_ext <<_ACEOF+/* end confdefs.h. */+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.+ For example, HP-UX 11i <limits.h> declares gettimeofday. */+#define $ac_func innocuous_$ac_func++/* System header to define __stub macros and hopefully few prototypes,+ which can conflict with char $ac_func (); below.+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since+ <limits.h> exists even on freestanding compilers. */++#ifdef __STDC__+# include <limits.h>+#else+# include <assert.h>+#endif++#undef $ac_func++/* Override any GCC internal prototype to avoid an error.+ Use char because int might match the return type of a GCC+ builtin and then its argument prototype would still apply. */+#ifdef __cplusplus+extern "C"+#endif+char $ac_func ();+/* The GNU C library defines this for functions which it implements+ to always fail with ENOSYS. Some functions are actually named+ something starting with __ and the normal name is an alias. */+#if defined __stub_$ac_func || defined __stub___$ac_func+choke me+#endif++int+main ()+{+return $ac_func ();+ ;+ return 0;+}+_ACEOF+rm -f conftest.$ac_objext conftest$ac_exeext+if { (ac_try="$ac_link"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5+ (eval "$ac_link") 2>conftest.er1+ ac_status=$?+ grep -v '^ *+' conftest.er1 >conftest.err+ rm -f conftest.er1+ cat conftest.err >&5+ echo "$as_me:$LINENO: \$? = $ac_status" >&5+ (exit $ac_status); } && {+ test -z "$ac_c_werror_flag" ||+ test ! -s conftest.err+ } && test -s conftest$ac_exeext &&+ $as_test_x conftest$ac_exeext; then+ eval "$as_ac_var=yes"+else+ echo "$as_me: failed program was:" >&5+sed 's/^/| /' conftest.$ac_ext >&5++ eval "$as_ac_var=no"+fi++rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \+ conftest$ac_exeext conftest.$ac_ext+fi+ac_res=`eval echo '${'$as_ac_var'}'`+ { echo "$as_me:$LINENO: result: $ac_res" >&5+echo "${ECHO_T}$ac_res" >&6; }+if test `eval echo '${'$as_ac_var'}'` = yes; then+ cat >>confdefs.h <<_ACEOF+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1+_ACEOF++fi+done++ # Avoid adding rt if absent or unneeded { echo "$as_me:$LINENO: checking for shm_open in -lrt" >&5 echo $ECHO_N "checking for shm_open in -lrt... $ECHO_C" >&6; }@@ -5801,7 +5895,7 @@ ### we'd like to return it; otherwise, we'll fake it. { echo "$as_me:$LINENO: checking return type of usleep" >&5 echo $ECHO_N "checking return type of usleep... $ECHO_C" >&6; }-if test "${cv_func_usleep_return_type+set}" = set; then+if test "${fptools_cv_func_usleep_return_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF@@ -5815,16 +5909,16 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "void[ ]+usleep" >/dev/null 2>&1; then- cv_func_usleep_return_type=void+ fptools_cv_func_usleep_return_type=void else- cv_func_usleep_return_type=int+ fptools_cv_func_usleep_return_type=int fi rm -f conftest* fi-{ echo "$as_me:$LINENO: result: $cv_func_usleep_return_type" >&5-echo "${ECHO_T}$cv_func_usleep_return_type" >&6; }-case "$cv_func_usleep_return_type" in+{ echo "$as_me:$LINENO: result: $fptools_cv_func_usleep_return_type" >&5+echo "${ECHO_T}$fptools_cv_func_usleep_return_type" >&6; }+case "$fptools_cv_func_usleep_return_type" in "void" ) cat >>confdefs.h <<\_ACEOF@@ -5838,7 +5932,7 @@ ### in common use return void. { echo "$as_me:$LINENO: checking return type of unsetenv" >&5 echo $ECHO_N "checking return type of unsetenv... $ECHO_C" >&6; }-if test "${cv_func_unsetenv_return_type+set}" = set; then+if test "${fptools_cv_func_unsetenv_return_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF@@ -5852,16 +5946,16 @@ _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "void[ ]+unsetenv" >/dev/null 2>&1; then- cv_func_unsetenv_return_type=void+ fptools_cv_func_unsetenv_return_type=void else- cv_func_unsetenv_return_type=int+ fptools_cv_func_unsetenv_return_type=int fi rm -f conftest* fi-{ echo "$as_me:$LINENO: result: $cv_func_unsetenv_return_type" >&5-echo "${ECHO_T}$cv_func_unsetenv_return_type" >&6; }-case "$cv_func_unsetenv_return_type" in+{ echo "$as_me:$LINENO: result: $fptools_cv_func_unsetenv_return_type" >&5+echo "${ECHO_T}$fptools_cv_func_unsetenv_return_type" >&6; }+case "$fptools_cv_func_unsetenv_return_type" in "void" ) cat >>confdefs.h <<\_ACEOF
configure.ac view
@@ -27,6 +27,7 @@ AC_CHECK_FUNCS([nanosleep]) AC_CHECK_FUNCS([ptsname]) AC_CHECK_FUNCS([setitimer])+AC_CHECK_FUNCS([readdir_r]) # Avoid adding rt if absent or unneeded AC_CHECK_LIB(rt, shm_open, [EXTRA_LIBS="$EXTRA_LIBS rt" CFLAGS="$CFLAGS -lrt"])@@ -69,12 +70,12 @@ ### On some systems usleep has no return value. If it does have one, ### we'd like to return it; otherwise, we'll fake it.-AC_CACHE_CHECK([return type of usleep], cv_func_usleep_return_type,+AC_CACHE_CHECK([return type of usleep], fptools_cv_func_usleep_return_type, [AC_EGREP_HEADER(changequote(<, >)<void[ ]+usleep>changequote([, ]), /usr/include/unistd.h,- [cv_func_usleep_return_type=void],- [cv_func_usleep_return_type=int])])-case "$cv_func_usleep_return_type" in+ [fptools_cv_func_usleep_return_type=void],+ [fptools_cv_func_usleep_return_type=int])])+case "$fptools_cv_func_usleep_return_type" in "void" ) AC_DEFINE([USLEEP_RETURNS_VOID], [1], [Define if the system headers declare usleep to return void.]) ;;@@ -82,12 +83,12 @@ ### POSIX.1003.1 unsetenv returns 0 or -1 (EINVAL), but older implementations ### in common use return void.-AC_CACHE_CHECK([return type of unsetenv], cv_func_unsetenv_return_type,+AC_CACHE_CHECK([return type of unsetenv], fptools_cv_func_unsetenv_return_type, [AC_EGREP_HEADER(changequote(<, >)<void[ ]+unsetenv>changequote([, ]), /usr/include/stdlib.h,- [cv_func_unsetenv_return_type=void],- [cv_func_unsetenv_return_type=int])])-case "$cv_func_unsetenv_return_type" in+ [fptools_cv_func_unsetenv_return_type=void],+ [fptools_cv_func_unsetenv_return_type=int])])+case "$fptools_cv_func_unsetenv_return_type" in "void" ) AC_DEFINE([UNSETENV_RETURNS_VOID], [1], [Define if stdlib.h declares unsetenv to return void.]) ;;
include/HsUnix.h view
@@ -127,6 +127,37 @@ // lstat is a macro on some platforms, so we need a wrapper: int __hsunix_mknod(const char *pathname, mode_t mode, dev_t dev); +#ifdef HAVE_GETPWENT+// getpwent is a macro on some platforms, so we need a wrapper:+struct passwd *__hsunix_getpwent(void);+#endif++#if HAVE_GETPWNAM_R+// getpwnam_r is a macro on some platforms, so we need a wrapper:+int __hsunix_getpwnam_r(const char *, struct passwd *, char *, size_t,+ struct passwd **);+#endif++#ifdef HAVE_GETPWUID_R+// getpwuid_r is a macro on some platforms, so we need a wrapper:+int __hsunix_getpwuid_r(uid_t, struct passwd *, char *, size_t,+ struct passwd **);+#endif++#ifdef HAVE_NANOSLEEP+// nanosleep is a macro on some platforms, so we need a wrapper:+int __hsunix_nanosleep(const struct timespec *, struct timespec *);+#endif++// opendir is a macro on some platforms, so we need a wrapper:+DIR *__hsunix_opendir(const char *);++// time is a macro on some platforms, so we need a wrapper:+time_t __hsunix_time(time_t *);++// times is a macro on some platforms, so we need a wrapper:+clock_t __hsunix_times(struct tms *);+ #ifdef HAVE_PTSNAME // I cannot figure out how to make the definitions of the following // functions visible in <stdlib.h> on Linux. But these definitions
include/HsUnixConfig.h view
@@ -163,6 +163,9 @@ /* Define to 1 if you have the <pwd.h> header file. */ #define HAVE_PWD_H 1 +/* Define to 1 if you have the `readdir_r' function. */+#define HAVE_READDIR_R 1+ /* Define to 1 if RTLD_DEFAULT is available. */ /* #undef HAVE_RTLDDEFAULT */
include/HsUnixConfig.h.in view
@@ -162,6 +162,9 @@ /* Define to 1 if you have the <pwd.h> header file. */ #undef HAVE_PWD_H +/* Define to 1 if you have the `readdir_r' function. */+#undef HAVE_READDIR_R+ /* Define to 1 if RTLD_DEFAULT is available. */ #undef HAVE_RTLDDEFAULT
unix.cabal view
@@ -1,8 +1,9 @@ name: unix-version: 2.3.2.0+version: 2.4.0.0 license: BSD3 license-file: LICENSE maintainer: libraries@haskell.org+bug-reports: http://hackage.haskell.org/trac/ghc/newticket?component=libraries/unix synopsis: POSIX functionality category: System description:@@ -12,29 +13,6 @@ IEEE Std. 1003.1). . The package is not supported under Windows (except under Cygwin).-build-type: Configure-exposed-modules:- System.Posix- System.Posix.DynamicLinker.Module- System.Posix.DynamicLinker.Prim- System.Posix.Directory- System.Posix.DynamicLinker- System.Posix.Env- System.Posix.Error- System.Posix.Files- System.Posix.IO- System.Posix.Process- System.Posix.Process.Internals- System.Posix.Resource- System.Posix.Temp- System.Posix.Terminal- System.Posix.Time- System.Posix.Unistd- System.Posix.User- System.Posix.Signals- System.Posix.Signals.Exts- System.Posix.Semaphore- System.Posix.SharedMem extra-source-files: config.guess config.sub install-sh configure.ac configure@@ -43,10 +21,41 @@ extra-tmp-files: config.log config.status autom4te.cache unix.buildinfo include/HsUnixConfig.h-build-depends: base-extensions: CPP, ForeignFunctionInterface, EmptyDataDecls-include-dirs: include-includes: HsUnix.h execvpe.h-install-includes:- HsUnix.h HsUnixConfig.h execvpe.h-c-sources: cbits/HsUnix.c cbits/execvpe.c+build-type: Configure+Cabal-Version: >= 1.6++Library+ exposed-modules:+ System.Posix+ System.Posix.DynamicLinker.Module+ System.Posix.DynamicLinker.Prim+ System.Posix.Directory+ System.Posix.DynamicLinker+ System.Posix.Env+ System.Posix.Error+ System.Posix.Files+ System.Posix.IO+ System.Posix.Process+ System.Posix.Process.Internals+ System.Posix.Resource+ System.Posix.Temp+ System.Posix.Terminal+ System.Posix.Time+ System.Posix.Unistd+ System.Posix.User+ System.Posix.Signals+ System.Posix.Signals.Exts+ System.Posix.Semaphore+ System.Posix.SharedMem+ build-depends: base >= 4.1 && < 4.3+ extensions: CPP, ForeignFunctionInterface, EmptyDataDecls+ include-dirs: include+ includes: HsUnix.h execvpe.h+ install-includes:+ HsUnix.h HsUnixConfig.h execvpe.h+ c-sources: cbits/HsUnix.c cbits/execvpe.c cbits/dirUtils.c++source-repository head+ type: darcs+ location: http://darcs.haskell.org/packages/unix/+