@@ -557,6 +557,19 @@ int mingw_mkdir(const char *path, int mode)
557557 return ret ;
558558}
559559
560+ /*
561+ * Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA
562+ * is documented in [1] as opening a writable file handle in append mode.
563+ * (It is believed that) this is atomic since it is maintained by the
564+ * kernel unlike the O_APPEND flag which is racily maintained by the CRT.
565+ *
566+ * [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants
567+ *
568+ * This trick does not appear to work for named pipes. Instead it creates
569+ * a named pipe client handle that cannot be written to. Callers should
570+ * just use the regular _wopen() for them. (And since client handle gets
571+ * bound to a unique server handle, it isn't really an issue.)
572+ */
560573static int mingw_open_append (wchar_t const * wfilename , int oflags , ...)
561574{
562575 HANDLE handle ;
@@ -576,17 +589,36 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
576589 NULL , create , FILE_ATTRIBUTE_NORMAL , NULL );
577590 if (handle == INVALID_HANDLE_VALUE )
578591 return errno = err_win_to_posix (GetLastError ()), -1 ;
592+
579593 /*
580594 * No O_APPEND here, because the CRT uses it only to reset the
581- * file pointer to EOF on write(); but that is not necessary
582- * for a file created with FILE_APPEND_DATA.
595+ * file pointer to EOF before each write(); but that is not
596+ * necessary (and may lead to races) for a file created with
597+ * FILE_APPEND_DATA.
583598 */
584599 fd = _open_osfhandle ((intptr_t )handle , O_BINARY );
585600 if (fd < 0 )
586601 CloseHandle (handle );
587602 return fd ;
588603}
589604
605+ #define IS_SBS (ch ) (((ch) == '/') || ((ch) == '\\'))
606+ /*
607+ * Does the pathname map to the local named pipe filesystem?
608+ * That is, does it have a "//./pipe/" prefix?
609+ */
610+ static int mingw_is_local_named_pipe_path (const char * filename )
611+ {
612+ return (IS_SBS (filename [0 ]) &&
613+ IS_SBS (filename [1 ]) &&
614+ filename [2 ] == '.' &&
615+ IS_SBS (filename [3 ]) &&
616+ !strncasecmp (filename + 4 , "pipe" , 4 ) &&
617+ IS_SBS (filename [8 ]) &&
618+ filename [9 ]);
619+ }
620+ #undef IS_SBS
621+
590622int mingw_open (const char * filename , int oflags , ...)
591623{
592624 typedef int (* open_fn_t )(wchar_t const * wfilename , int oflags , ...);
@@ -603,7 +635,7 @@ int mingw_open (const char *filename, int oflags, ...)
603635 if (filename && !strcmp (filename , "/dev/null" ))
604636 filename = "nul" ;
605637
606- if (oflags & O_APPEND )
638+ if (( oflags & O_APPEND ) && ! mingw_is_local_named_pipe_path ( filename ) )
607639 open_fn = mingw_open_append ;
608640 else
609641 open_fn = _wopen ;
@@ -1939,6 +1971,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
19391971 int status ;
19401972 if (waitpid (pid , & status , 0 ) < 0 )
19411973 status = 255 ;
1974+ trace2_exec_result (status );
19421975 exit (status );
19431976 }
19441977 pid = 1 ; /* indicate that we tried but failed */
@@ -1959,6 +1992,7 @@ int mingw_execv(const char *cmd, char *const *argv)
19591992 return -1 ;
19601993 if (waitpid (pid , & status , 0 ) < 0 )
19611994 status = 255 ;
1995+ trace2_exec_result (status );
19621996 exit (status );
19631997 }
19641998 return -1 ;
0 commit comments