diff mbox

[Ada] Stream output to fifos

Message ID 20160418122719.GA130771@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 18, 2016, 12:27 p.m. UTC
This patch fixes a regression in stream output to fifos (named pipes). When a
fifo is opened for output, the process should block until another process opens
the fifo for reading. This is now (again) the case.

Tested on x86_64-pc-linux-gnu, committed on trunk

2016-04-18  Bob Duff  <duff@adacore.com>

	* s-fileio.adb (Fopen_Mode): If Mode = Out_File, and the file
	exists, and it's a fifo, we use "w" as the open string instead of
	"r+". This is necessary to make a write to the fifo block until
	a reader is ready.
diff mbox

Patch

Index: cstreams.c
===================================================================
--- cstreams.c	(revision 235093)
+++ cstreams.c	(working copy)
@@ -39,6 +39,8 @@ 
 
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #ifdef _AIX
 /* needed to avoid conflicting declarations */
@@ -320,6 +322,24 @@ 
 }
 #endif
 
+/* Returns true if the path names a fifo (i.e. a named pipe). */
+int
+__gnat_is_fifo (const char* path)
+{
+/* Posix defines S_ISFIFO as a macro. If the macro doesn't exist, we return
+   false. */
+#ifdef S_ISFIFO
+  struct stat buf;
+  const int status = stat(path, &buf);
+  if (status == 0)
+    return S_ISFIFO(buf.st_mode);
+#endif
+
+  /* S_ISFIFO is not available, or stat got an error (probably
+     file not found). */
+  return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
Index: s-fileio.adb
===================================================================
--- s-fileio.adb	(revision 235093)
+++ s-fileio.adb	(working copy)
@@ -106,17 +106,18 @@ 
    --  Holds open string (longest is "w+b" & nul)
 
    procedure Fopen_Mode
-     (Mode    : File_Mode;
+     (Namestr : String;
+      Mode    : File_Mode;
       Text    : Boolean;
       Creat   : Boolean;
       Amethod : Character;
       Fopstr  : out Fopen_String);
    --  Determines proper open mode for a file to be opened in the given Ada
-   --  mode. Text is true for a text file and false otherwise, and Creat is
-   --  true for a create call, and False for an open call. The value stored
-   --  in Fopstr is a nul-terminated string suitable for a call to fopen or
-   --  freopen. Amethod is the character designating the access method from
-   --  the Access_Method field of the FCB.
+   --  mode. Namestr is the NUL-terminated file name. Text is true for a text
+   --  file and false otherwise, and Creat is true for a create call, and False
+   --  for an open call. The value stored in Fopstr is a nul-terminated string
+   --  suitable for a call to fopen or freopen. Amethod is the character
+   --  designating the access method from the Access_Method field of the FCB.
 
    function Errno_Message
      (Name  : String;
@@ -433,10 +434,14 @@ 
    --                                     OPEN         CREATE
    --     Append_File                     "r+"           "w+"
    --     In_File                         "r"            "w+"
-   --     Out_File (Direct_IO, Stream_IO) "r+"           "w"
+   --     Out_File (Direct_IO, Stream_IO) "r+" [*]       "w"
    --     Out_File (others)               "w"            "w"
    --     Inout_File                      "r+"           "w+"
 
+   --  [*] Except that for Out_File, if the file exists and is a fifo (i.e. a
+   --  named pipe), we use "w" instead of "r+". This is necessary to make a
+   --  write to the fifo block until a reader is ready.
+
    --  Note: we do not use "a" or "a+" for Append_File, since this would not
    --  work in the case of stream files, where even if in append file mode,
    --  you can reset to earlier points in the file. The caller must use the
@@ -458,7 +463,8 @@ 
    --  to the mode, depending on the setting of Text.
 
    procedure Fopen_Mode
-     (Mode    : File_Mode;
+     (Namestr : String;
+      Mode    : File_Mode;
       Text    : Boolean;
       Creat   : Boolean;
       Amethod : Character;
@@ -466,6 +472,9 @@ 
    is
       Fptr : Positive;
 
+      function is_fifo (Path : Address) return Integer;
+      pragma Import (C, is_fifo, "__gnat_is_fifo");
+
    begin
       case Mode is
          when In_File =>
@@ -479,7 +488,10 @@ 
             end if;
 
          when Out_File =>
-            if Amethod in 'D' | 'S' and then not Creat then
+            if Amethod in 'D' | 'S'
+              and then not Creat
+              and then is_fifo (Namestr'Address) = 0
+            then
                Fopstr (1) := 'r';
                Fopstr (2) := '+';
                Fptr := 3;
@@ -1045,7 +1057,7 @@ 
 
          else
             Fopen_Mode
-              (Mode, Text_Encoding in Text_Content_Encoding,
+              (Namestr, Mode, Text_Encoding in Text_Content_Encoding,
                Creat, Amethod, Fopstr);
 
             --  A special case, if we are opening (OPEN case) a file and the
@@ -1218,7 +1230,7 @@ 
 
       else
          Fopen_Mode
-           (Mode, File.Text_Encoding in Text_Content_Encoding,
+           (File.Name.all, Mode, File.Text_Encoding in Text_Content_Encoding,
             False, File.Access_Method, Fopstr);
 
          File.Stream := freopen