# HG changeset patch # User Christian Brabandt # Date 1457553605 -3600 # Node ID c1aae3a7927938975b1b55ef2c65fda3cc4c23ec # Parent 552c13b08d0bd444e6e0287818986705ca01aef7 commit https://github.com/vim/vim/commit/d5d3d307ddb824f59a2f2516c4b6a6d48762aa58 Author: Bram Moolenaar 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) diff --git a/src/os_win32.c b/src/os_win32.c --- 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; diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim --- 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 diff --git a/src/version.c b/src/version.c --- 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,