-
Notifications
You must be signed in to change notification settings - Fork 7
/
file.cpp
100 lines (79 loc) · 3.03 KB
/
file.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "StdAfx.h"
#include "file.h"
#include "FilePipe.h"
#include "SystemError.h"
#include <codecvt>
using namespace Linter;
std::string File::exec(std::wstring commandLine, const nonstd::optional<std::string> &str)
{
if (!m_file.empty())
{
commandLine += ' ';
commandLine += '"';
commandLine += m_file;
commandLine += '"';
}
const auto stdoutpipe = FilePipe::create();
const auto stderrpipe = FilePipe::create();
const auto stdinpipe = FilePipe::create();
//Stop my handle being inherited by the child
FilePipe::detachFromParent(stdoutpipe.m_reader);
FilePipe::detachFromParent(stderrpipe.m_reader);
FilePipe::detachFromParent(stdinpipe.m_writer);
STARTUPINFO startInfo = {0};
startInfo.cb = sizeof(STARTUPINFO);
startInfo.hStdError = stderrpipe.m_writer;
startInfo.hStdOutput = stdoutpipe.m_writer;
startInfo.hStdInput = stdinpipe.m_reader;
startInfo.dwFlags |= STARTF_USESTDHANDLES;
PROCESS_INFORMATION procInfo = {0};
BOOL isSuccess = CreateProcess(NULL,
const_cast<wchar_t *>(commandLine.c_str()), // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NO_WINDOW, // creation flags
NULL, // use parent's environment
m_directory.c_str(), // use parent's current directory
&startInfo, // STARTUPINFO pointer
&procInfo); // receives PROCESS_INFORMATION
if (!isSuccess)
{
DWORD const error{GetLastError()};
std::string command{std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(commandLine)};
throw SystemError(error, "Can't execute command: " + command);
}
if (str.has_value())
{
stdinpipe.m_writer.writeFile(str.value());
}
//We need to close all the handles for this end otherwise strange things happen.
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
stdoutpipe.m_writer.close();
stderrpipe.m_writer.close();
stdinpipe.m_writer.close();
return stdoutpipe.m_reader.readFile();
}
File::File(const std::wstring &fileName, const std::wstring &directory) : m_fileName(fileName), m_directory(directory)
{
}
File::~File()
{
if (!m_file.empty())
{
_wunlink(m_file.c_str());
}
}
void File::write(const std::string &data)
{
if (data.empty())
{
return;
}
const std::wstring tempFileName = m_directory + L"/" + m_fileName + L".temp.linter.file.tmp";
HandleWrapper fileHandle{
CreateFile(tempFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY, NULL)};
fileHandle.writeFile(data);
m_file = tempFileName;
}