changeset 8471:c1aae3a79279 v7.4.1526

commit https://github.com/vim/vim/commit/d5d3d307ddb824f59a2f2516c4b6a6d48762aa58 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Mar 9 20:54:51 2016 +0100 patch 7.4.1526 Problem: Writing to file and not connecting a channel doesn't work for MS-Windows. Solution: Make it work. (Yasuhiro Matsumoto)
author Christian Brabandt <cb@256bit.org>
date Wed, 09 Mar 2016 21:00:05 +0100
parents 552c13b08d0b
children d45ad00fd8d2
files src/os_win32.c src/testdir/test_channel.vim src/version.c
diffstat 3 files changed, 57 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -4992,41 +4992,6 @@ mch_call_shell(
 }
 
 #if defined(FEAT_JOB) || defined(PROTO)
-    HANDLE
-job_io_file_open(
-	char_u *fname,
-	DWORD dwDesiredAccess,
-	DWORD dwShareMode,
-	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-	DWORD dwCreationDisposition,
-	DWORD dwFlagsAndAttributes)
-{
-    HANDLE h;
-#ifdef FEAT_MBYTE
-    WCHAR *wn = NULL;
-    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-    {
-	wn = enc_to_utf16(fname, NULL);
-	if (wn != NULL)
-	{
-	    h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
-		     lpSecurityAttributes, dwCreationDisposition,
-		     dwFlagsAndAttributes, NULL);
-	    vim_free(wn);
-	    if (h == INVALID_HANDLE_VALUE
-			  && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
-		wn = NULL;
-	}
-    }
-    if (wn == NULL)
-#endif
-
-	h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode,
-		     lpSecurityAttributes, dwCreationDisposition,
-		     dwFlagsAndAttributes, NULL);
-    return h;
-}
-
     void
 mch_start_job(char *cmd, job_T *job, jobopt_T *options)
 {
@@ -5034,15 +4999,22 @@ mch_start_job(char *cmd, job_T *job, job
     PROCESS_INFORMATION	pi;
     HANDLE		jo;
 # ifdef FEAT_CHANNEL
-    channel_T		*channel;
-    int			use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
-    int			use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
-    int			use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
-    int			use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
+    SECURITY_ATTRIBUTES saAttr;
+    channel_T		*channel = NULL;
     HANDLE		ifd[2];
     HANDLE		ofd[2];
     HANDLE		efd[2];
-    SECURITY_ATTRIBUTES saAttr;
+
+    int		use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
+    int		use_null_for_out = options->jo_io[PART_OUT] == JIO_NULL;
+    int		use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL;
+    int		use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
+    int		use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
+    int		use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
+    int		use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
+
+    if (use_out_for_err && use_null_for_out)
+	use_null_for_err = TRUE;
 
     ifd[0] = INVALID_HANDLE_VALUE;
     ifd[1] = INVALID_HANDLE_VALUE;
@@ -5050,10 +5022,6 @@ mch_start_job(char *cmd, job_T *job, job
     ofd[1] = INVALID_HANDLE_VALUE;
     efd[0] = INVALID_HANDLE_VALUE;
     efd[1] = INVALID_HANDLE_VALUE;
-
-    channel = add_channel();
-    if (channel == NULL)
-	return;
 # endif
 
     jo = CreateJobObject(NULL, NULL);
@@ -5078,55 +5046,64 @@ mch_start_job(char *cmd, job_T *job, job
     {
 	char_u *fname = options->jo_io_name[PART_IN];
 
-	ifd[0] = job_io_file_open(fname, GENERIC_READ, FILE_SHARE_READ,
-		&saAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);
-	if (ifd[0] == INVALID_HANDLE_VALUE)
+	int fd = mch_open((char *)fname, O_RDONLY, 0);
+	if (fd < 0)
 	{
 	    EMSG2(_(e_notopen), fname);
 	    goto failed;
 	}
-    }
-    else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
-	    || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
+	ifd[0] = (HANDLE)_get_osfhandle(fd);
+    }
+    else if (!use_null_for_in &&
+	    (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
+	    || !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)))
 	goto failed;
 
     if (use_file_for_out)
     {
 	char_u *fname = options->jo_io_name[PART_OUT];
 
-	ofd[0] = job_io_file_open(fname, GENERIC_WRITE, FILE_SHARE_WRITE,
-		&saAttr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL);
-	if (ofd[0] == INVALID_HANDLE_VALUE)
+	int fd = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+	if (fd < 0)
 	{
 	    EMSG2(_(e_notopen), fname);
 	    goto failed;
 	}
-    }
-    else if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
-	    || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
+	ofd[1] = (HANDLE)_get_osfhandle(fd);
+    }
+    else if (!use_null_for_out &&
+	    (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
+	    || !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)))
 	goto failed;
 
     if (use_file_for_err)
     {
 	char_u *fname = options->jo_io_name[PART_ERR];
 
-	efd[0] = job_io_file_open(fname, GENERIC_WRITE, FILE_SHARE_WRITE,
-		&saAttr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL);
-	if (efd[0] == INVALID_HANDLE_VALUE)
+	int fd = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (fd < 0)
 	{
 	    EMSG2(_(e_notopen), fname);
 	    goto failed;
 	}
-    }
-    else if (!use_out_for_err
-	   && (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
+	efd[1] = (HANDLE)_get_osfhandle(fd);
+    }
+    else if (!use_out_for_err && !use_null_for_err &&
+	    (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
 	    || !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
 	goto failed;
 
     si.dwFlags |= STARTF_USESTDHANDLES;
     si.hStdInput = ifd[0];
-    si.hStdOutput = use_file_for_out ? ofd[0] : ofd[1];
-    si.hStdError = use_out_for_err && !use_file_for_err ? ofd[1] : efd[1];
+    si.hStdOutput = ofd[1];
+    si.hStdError = use_out_for_err ? ofd[1] : efd[1];
+
+    if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
+    {
+	channel = add_channel();
+	if (channel == NULL)
+	    goto failed;
+    }
 # endif
 
     if (!vim_create_process(cmd, TRUE,
@@ -5159,18 +5136,24 @@ mch_start_job(char *cmd, job_T *job, job
 	CloseHandle(ifd[0]);
     if (!use_file_for_out)
 	CloseHandle(ofd[1]);
-    if (!use_out_for_err)
+    if (!use_out_for_err && !use_file_for_err)
 	CloseHandle(efd[1]);
 
     job->jv_channel = channel;
-    channel_set_pipes(channel,
-		    use_file_for_in ? INVALID_FD : (sock_T)ifd[1],
-		    (sock_T)ofd[0],
-		    use_out_for_err ? INVALID_FD : (sock_T)efd[0]);
-    channel_set_job(channel, job, options);
+    if (channel != NULL)
+    {
+	channel_set_pipes(channel,
+		      use_file_for_in || use_null_for_in
+					      ? INVALID_FD : (sock_T)ifd[1],
+		      use_file_for_out || use_null_for_out
+					     ? INVALID_FD : (sock_T)ofd[0],
+		      use_out_for_err || use_file_for_err || use_null_for_err
+					    ? INVALID_FD : (sock_T)efd[0]);
+	channel_set_job(channel, job, options);
 #  ifdef FEAT_GUI
-    channel_gui_register(channel);
+	channel_gui_register(channel);
 #  endif
+    }
 # endif
     return;
 
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -550,10 +550,6 @@ func Test_nl_write_out_file()
   if !has('job')
     return
   endif
-  " TODO: make this work for MS-Windows
-  if !has('unix')
-    return
-  endif
   call ch_log('Test_nl_write_out_file()')
   let job = job_start(s:python . " test_channel_pipe.py",
 	\ {'out-io': 'file', 'out-name': 'Xoutput'})
@@ -575,10 +571,6 @@ func Test_nl_write_err_file()
   if !has('job')
     return
   endif
-  " TODO: make this work for MS-Windows
-  if !has('unix')
-    return
-  endif
   call ch_log('Test_nl_write_err_file()')
   let job = job_start(s:python . " test_channel_pipe.py",
 	\ {'err-io': 'file', 'err-name': 'Xoutput'})
@@ -600,10 +592,6 @@ func Test_nl_write_both_file()
   if !has('job')
     return
   endif
-  " TODO: make this work for MS-Windows
-  if !has('unix')
-    return
-  endif
   call ch_log('Test_nl_write_both_file()')
   let job = job_start(s:python . " test_channel_pipe.py",
 	\ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'})
@@ -838,10 +826,6 @@ func Test_pipe_null()
   if !has('job')
     return
   endif
-  " TODO: implement this for MS-Windows
-  if !has('unix')
-    return
-  endif
   call ch_log('Test_pipe_null()')
 
   " We cannot check that no I/O works, we only check that the job starts
--- a/src/version.c
+++ b/src/version.c
@@ -744,6 +744,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1526,
+/**/
     1525,
 /**/
     1524,