Skip to content

Commit d5d3d30

Browse files
committed
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)
1 parent beb003b commit d5d3d30

3 files changed

Lines changed: 54 additions & 85 deletions

File tree

src/os_win32.c

Lines changed: 52 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4992,68 +4992,36 @@ mch_call_shell(
49924992
}
49934993

49944994
#if defined(FEAT_JOB) || defined(PROTO)
4995-
HANDLE
4996-
job_io_file_open(
4997-
char_u *fname,
4998-
DWORD dwDesiredAccess,
4999-
DWORD dwShareMode,
5000-
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
5001-
DWORD dwCreationDisposition,
5002-
DWORD dwFlagsAndAttributes)
5003-
{
5004-
HANDLE h;
5005-
#ifdef FEAT_MBYTE
5006-
WCHAR *wn = NULL;
5007-
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
5008-
{
5009-
wn = enc_to_utf16(fname, NULL);
5010-
if (wn != NULL)
5011-
{
5012-
h = CreateFileW(wn, dwDesiredAccess, dwShareMode,
5013-
lpSecurityAttributes, dwCreationDisposition,
5014-
dwFlagsAndAttributes, NULL);
5015-
vim_free(wn);
5016-
if (h == INVALID_HANDLE_VALUE
5017-
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
5018-
wn = NULL;
5019-
}
5020-
}
5021-
if (wn == NULL)
5022-
#endif
5023-
5024-
h = CreateFile((LPCSTR)fname, dwDesiredAccess, dwShareMode,
5025-
lpSecurityAttributes, dwCreationDisposition,
5026-
dwFlagsAndAttributes, NULL);
5027-
return h;
5028-
}
5029-
50304995
void
50314996
mch_start_job(char *cmd, job_T *job, jobopt_T *options)
50324997
{
50334998
STARTUPINFO si;
50344999
PROCESS_INFORMATION pi;
50355000
HANDLE jo;
50365001
# ifdef FEAT_CHANNEL
5037-
channel_T *channel;
5038-
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
5039-
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
5040-
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
5041-
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
5002+
SECURITY_ATTRIBUTES saAttr;
5003+
channel_T *channel = NULL;
50425004
HANDLE ifd[2];
50435005
HANDLE ofd[2];
50445006
HANDLE efd[2];
5045-
SECURITY_ATTRIBUTES saAttr;
5007+
5008+
int use_null_for_in = options->jo_io[PART_IN] == JIO_NULL;
5009+
int use_null_for_out = options->jo_io[PART_OUT] == JIO_NULL;
5010+
int use_null_for_err = options->jo_io[PART_ERR] == JIO_NULL;
5011+
int use_file_for_in = options->jo_io[PART_IN] == JIO_FILE;
5012+
int use_file_for_out = options->jo_io[PART_OUT] == JIO_FILE;
5013+
int use_file_for_err = options->jo_io[PART_ERR] == JIO_FILE;
5014+
int use_out_for_err = options->jo_io[PART_ERR] == JIO_OUT;
5015+
5016+
if (use_out_for_err && use_null_for_out)
5017+
use_null_for_err = TRUE;
50465018

50475019
ifd[0] = INVALID_HANDLE_VALUE;
50485020
ifd[1] = INVALID_HANDLE_VALUE;
50495021
ofd[0] = INVALID_HANDLE_VALUE;
50505022
ofd[1] = INVALID_HANDLE_VALUE;
50515023
efd[0] = INVALID_HANDLE_VALUE;
50525024
efd[1] = INVALID_HANDLE_VALUE;
5053-
5054-
channel = add_channel();
5055-
if (channel == NULL)
5056-
return;
50575025
# endif
50585026

50595027
jo = CreateJobObject(NULL, NULL);
@@ -5078,55 +5046,64 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
50785046
{
50795047
char_u *fname = options->jo_io_name[PART_IN];
50805048

5081-
ifd[0] = job_io_file_open(fname, GENERIC_READ, FILE_SHARE_READ,
5082-
&saAttr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);
5083-
if (ifd[0] == INVALID_HANDLE_VALUE)
5049+
int fd = mch_open((char *)fname, O_RDONLY, 0);
5050+
if (fd < 0)
50845051
{
50855052
EMSG2(_(e_notopen), fname);
50865053
goto failed;
50875054
}
5055+
ifd[0] = (HANDLE)_get_osfhandle(fd);
50885056
}
5089-
else if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
5090-
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0))
5057+
else if (!use_null_for_in &&
5058+
(!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
5059+
|| !pSetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)))
50915060
goto failed;
50925061

50935062
if (use_file_for_out)
50945063
{
50955064
char_u *fname = options->jo_io_name[PART_OUT];
50965065

5097-
ofd[0] = job_io_file_open(fname, GENERIC_WRITE, FILE_SHARE_WRITE,
5098-
&saAttr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL);
5099-
if (ofd[0] == INVALID_HANDLE_VALUE)
5066+
int fd = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
5067+
if (fd < 0)
51005068
{
51015069
EMSG2(_(e_notopen), fname);
51025070
goto failed;
51035071
}
5072+
ofd[1] = (HANDLE)_get_osfhandle(fd);
51045073
}
5105-
else if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
5106-
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0))
5074+
else if (!use_null_for_out &&
5075+
(!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
5076+
|| !pSetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)))
51075077
goto failed;
51085078

51095079
if (use_file_for_err)
51105080
{
51115081
char_u *fname = options->jo_io_name[PART_ERR];
51125082

5113-
efd[0] = job_io_file_open(fname, GENERIC_WRITE, FILE_SHARE_WRITE,
5114-
&saAttr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL);
5115-
if (efd[0] == INVALID_HANDLE_VALUE)
5083+
int fd = mch_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
5084+
if (fd < 0)
51165085
{
51175086
EMSG2(_(e_notopen), fname);
51185087
goto failed;
51195088
}
5089+
efd[1] = (HANDLE)_get_osfhandle(fd);
51205090
}
5121-
else if (!use_out_for_err
5122-
&& (!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
5091+
else if (!use_out_for_err && !use_null_for_err &&
5092+
(!CreatePipe(&efd[0], &efd[1], &saAttr, 0)
51235093
|| !pSetHandleInformation(efd[0], HANDLE_FLAG_INHERIT, 0)))
51245094
goto failed;
51255095

51265096
si.dwFlags |= STARTF_USESTDHANDLES;
51275097
si.hStdInput = ifd[0];
5128-
si.hStdOutput = use_file_for_out ? ofd[0] : ofd[1];
5129-
si.hStdError = use_out_for_err && !use_file_for_err ? ofd[1] : efd[1];
5098+
si.hStdOutput = ofd[1];
5099+
si.hStdError = use_out_for_err ? ofd[1] : efd[1];
5100+
5101+
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
5102+
{
5103+
channel = add_channel();
5104+
if (channel == NULL)
5105+
goto failed;
5106+
}
51305107
# endif
51315108

51325109
if (!vim_create_process(cmd, TRUE,
@@ -5159,18 +5136,24 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
51595136
CloseHandle(ifd[0]);
51605137
if (!use_file_for_out)
51615138
CloseHandle(ofd[1]);
5162-
if (!use_out_for_err)
5139+
if (!use_out_for_err && !use_file_for_err)
51635140
CloseHandle(efd[1]);
51645141

51655142
job->jv_channel = channel;
5166-
channel_set_pipes(channel,
5167-
use_file_for_in ? INVALID_FD : (sock_T)ifd[1],
5168-
(sock_T)ofd[0],
5169-
use_out_for_err ? INVALID_FD : (sock_T)efd[0]);
5170-
channel_set_job(channel, job, options);
5143+
if (channel != NULL)
5144+
{
5145+
channel_set_pipes(channel,
5146+
use_file_for_in || use_null_for_in
5147+
? INVALID_FD : (sock_T)ifd[1],
5148+
use_file_for_out || use_null_for_out
5149+
? INVALID_FD : (sock_T)ofd[0],
5150+
use_out_for_err || use_file_for_err || use_null_for_err
5151+
? INVALID_FD : (sock_T)efd[0]);
5152+
channel_set_job(channel, job, options);
51715153
# ifdef FEAT_GUI
5172-
channel_gui_register(channel);
5154+
channel_gui_register(channel);
51735155
# endif
5156+
}
51745157
# endif
51755158
return;
51765159

src/testdir/test_channel.vim

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -550,10 +550,6 @@ func Test_nl_write_out_file()
550550
if !has('job')
551551
return
552552
endif
553-
" TODO: make this work for MS-Windows
554-
if !has('unix')
555-
return
556-
endif
557553
call ch_log('Test_nl_write_out_file()')
558554
let job = job_start(s:python . " test_channel_pipe.py",
559555
\ {'out-io': 'file', 'out-name': 'Xoutput'})
@@ -575,10 +571,6 @@ func Test_nl_write_err_file()
575571
if !has('job')
576572
return
577573
endif
578-
" TODO: make this work for MS-Windows
579-
if !has('unix')
580-
return
581-
endif
582574
call ch_log('Test_nl_write_err_file()')
583575
let job = job_start(s:python . " test_channel_pipe.py",
584576
\ {'err-io': 'file', 'err-name': 'Xoutput'})
@@ -600,10 +592,6 @@ func Test_nl_write_both_file()
600592
if !has('job')
601593
return
602594
endif
603-
" TODO: make this work for MS-Windows
604-
if !has('unix')
605-
return
606-
endif
607595
call ch_log('Test_nl_write_both_file()')
608596
let job = job_start(s:python . " test_channel_pipe.py",
609597
\ {'out-io': 'file', 'out-name': 'Xoutput', 'err-io': 'out'})
@@ -838,10 +826,6 @@ func Test_pipe_null()
838826
if !has('job')
839827
return
840828
endif
841-
" TODO: implement this for MS-Windows
842-
if !has('unix')
843-
return
844-
endif
845829
call ch_log('Test_pipe_null()')
846830

847831
" We cannot check that no I/O works, we only check that the job starts

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1526,
746748
/**/
747749
1525,
748750
/**/

0 commit comments

Comments
 (0)