Throw a proper exception if getUserEntryForName fails to find an entry
authorIan Lynagh <igloo@earth.li>
Tue, 15 Jan 2008 02:05:47 +0000 (02:05 +0000)
committerIan Lynagh <igloo@earth.li>
Tue, 15 Jan 2008 02:05:47 +0000 (02:05 +0000)
Fixes trac #2033.

System/Posix/User.hsc

index 7ec49b6..d3af7d6 100644 (file)
@@ -55,7 +55,7 @@ import Control.Concurrent.MVar  ( newMVar, withMVar )
 #ifdef HAVE_GETPWENT
 import Control.Exception
 #endif
-#ifdef HAVE_GETGRNAM_R
+#if defined(HAVE_GETGRNAM_R) || defined(HAVE_GETPWNAM_R)
 import Control.Monad
 import System.IO.Error
 #endif
@@ -314,17 +314,22 @@ getUserEntryForName :: String -> IO UserEntry
 getUserEntryForName name = do
   allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
     allocaBytes pwBufSize $ \pbuf ->
-      alloca $ \ pppw -> 
-       withCString name $ \ pstr -> do
+      alloca $ \ pppw ->
+        withCString name $ \ pstr -> do
           throwErrorIfNonZero_ "getUserEntryForName" $
-              c_getpwnam_r pstr ppw pbuf (fromIntegral pwBufSize) pppw
-         throwErrnoIfNull "getUserEntryForName" $
-               peekElemOff pppw 0
-         unpackUserEntry ppw
+            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
 
 foreign import ccall unsafe "getpwnam_r"
-  c_getpwnam_r :: CString -> Ptr CPasswd -> 
-                       CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
+  c_getpwnam_r :: CString -> Ptr CPasswd
+               -> CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
 #elif HAVE_GETPWNAM
 getUserEntryForName name = do
   withCString name $ \ pstr -> do