00001 #ifndef FILE_DIFFER_IMPLEMENTATION_FILE
00002 #define FILE_DIFFER_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "file_differ.h"
00019
00020 #include <basis/convert_utf.h>
00021 #include <basis/istring.h>
00022 #include <basis/portable.h>
00023
00024 #include <stdio.h>
00025
00026 #define BUFSIZE 4096
00027
00028 bool file_differ::diff_files(const istring &_file1, const istring &_file2, const istring &_options,
00029 istring &_results, istring &_error)
00030 {
00031 _results.reset();
00032
00033 #ifdef __WIN32__
00034
00035 SECURITY_ATTRIBUTES saAttr;
00036 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
00037 saAttr.bInheritHandle = true;
00038 saAttr.lpSecurityDescriptor = NULL;
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
00050
00051
00052 HANDLE hChildStdoutRd, hChildStdoutWr;
00053 if( false == CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0) )
00054 {
00055 _error = "Stdout pipe creation failed";
00056 return false;
00057 }
00058
00059
00060 if( false == SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) )
00061 {
00062 _error = "Redirecting STDOUT failed";
00063 return false;
00064 }
00065
00066
00067 HANDLE hChildStdoutRdDup;
00068 if( false == DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
00069 GetCurrentProcess(), &hChildStdoutRdDup , 0,
00070 false,
00071 DUPLICATE_SAME_ACCESS) )
00072 {
00073 _error = "DuplicateHandle failed";
00074 return false;
00075 }
00076 CloseHandle(hChildStdoutRd);
00077
00078
00079
00080 PROCESS_INFORMATION piProcInfo;
00081 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
00082
00083
00084 STARTUPINFO siStartInfo;
00085 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
00086 siStartInfo.cb = sizeof(STARTUPINFO);
00087
00088
00089 siStartInfo.dwFlags = STARTF_USESTDHANDLES;
00090 siStartInfo.hStdOutput = hChildStdoutWr;
00091 siStartInfo.hStdError = hChildStdoutWr;
00092
00093
00094 isprintf cmdline("diff %s %s %s", _options.s(), _file1.s(), _file2.s());
00095 if( !CreateProcess(NULL,
00096 to_unicode_temp(cmdline),
00097 NULL,
00098 NULL,
00099 true,
00100 CREATE_NO_WINDOW,
00101 NULL,
00102 NULL,
00103 &siStartInfo,
00104 &piProcInfo) )
00105 {
00106 LPVOID lpMsgBuf;
00107 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
00108 FORMAT_MESSAGE_IGNORE_INSERTS,
00109 NULL,
00110 GetLastError(),
00111 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00112 (LPTSTR) &lpMsgBuf,
00113 0,
00114 NULL);
00115 _error = isprintf("Create process failed: %s", (LPCTSTR)lpMsgBuf);
00116
00117 LocalFree( lpMsgBuf );
00118 return false;
00119 }
00120
00121
00122 if( false == SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout) )
00123 {
00124 _error = "Re-redirecting Stdout failed";
00125 return false;
00126 }
00127
00128
00129
00130 if( false == CloseHandle(hChildStdoutWr) )
00131 {
00132 _error = "Closing handle failed";
00133 return false;
00134 }
00135
00136
00137 DWORD dwRead;
00138 CHAR chBuf[BUFSIZE];
00139 HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
00140 for (;;)
00141 {
00142 chBuf[0] = '\0';
00143 if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE - 1, &dwRead, NULL) || dwRead == 0)
00144 break;
00145 chBuf[dwRead] = '\0';
00146 _results += chBuf;
00147 }
00148 #elif defined(__UNIX__)
00149 if (!_file1 || !_file2 || !_options || !_error) {}
00150
00151 #else
00152
00153 #endif
00154
00155 return true;
00156 }
00157
00158
00159 void file_differ::AddCRs(istring &_string)
00160 {
00161 const istring addin("\r");
00162 for( int i = 0; i < _string.length(); ++i )
00163 {
00164 if( ('\n' == _string[i]) && ((i == 0) || ('\r' != _string[i-1])) )
00165 {
00166 _string.insert(i, addin);
00167 ++i;
00168 }
00169 }
00170 }
00171
00172
00173 #endif //FILE_DIFFER_IMPLEMENTATION_FILE
00174