diff --git a/src/system.h b/src/system.h
index 09498a172..71a2be42a 100644
--- a/src/system.h
+++ b/src/system.h
@@ -136,13 +136,26 @@ target_directory_operand (char const *file)
   if (must_be_working_directory (file))
     return AT_FDCWD;
 
-  int fd = open (file, O_PATHSEARCH | O_DIRECTORY);
+  int fd = -1;
+  bool is_a_dir = false;
+  struct stat st;
+
+  /* On old systems like Solaris 10, check with stat first
+     lest we try to open a fifo for example and hang.  */
+  if (!O_DIRECTORY && stat (file, &st) == 0)
+    {
+      is_a_dir = !!S_ISDIR (st.st_mode);
+      if (!is_a_dir)
+        errno = ENOTDIR;
+    }
+
+  if (O_DIRECTORY || is_a_dir)
+    fd = open (file, O_PATHSEARCH | O_DIRECTORY);
 
   if (!O_DIRECTORY && 0 <= fd)
     {
-      /* On old systems like Solaris 10 that do not support O_DIRECTORY,
-         check by hand whether FILE is a directory.  */
-      struct stat st;
+      /* On old systems like Solaris 10 double check type,
+         to ensure we've opened a directory.  */
       int err;
       if (fstat (fd, &st) != 0 ? (err = errno, true)
           : !S_ISDIR (st.st_mode) && (err = ENOTDIR, true))