source: trunk/tools/configure/environment.cpp@ 109

Last change on this file since 109 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 23.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "environment.h"
43
44#include <process.h>
45#include <iostream>
46#include <qdebug.h>
47#include <QDir>
48#include <QStringList>
49#include <QMap>
50#include <QDir>
51#include <QFile>
52#include <QFileInfo>
53
54//#define CONFIGURE_DEBUG_EXECUTE
55//#define CONFIGURE_DEBUG_CP_DIR
56
57using namespace std;
58
59#ifdef Q_OS_WIN32
60#include <qt_windows.h>
61#endif
62
63
64QT_BEGIN_NAMESPACE
65
66struct CompilerInfo{
67 Compiler compiler;
68 const char *compilerStr;
69 const char *regKey;
70 const char *executable;
71} compiler_info[] = {
72 // The compilers here are sorted in a reversed-preferred order
73 {CC_BORLAND, "Borland C++", 0, "bcc32.exe"},
74 {CC_MINGW, "MinGW (Minimalist GNU for Windows)", 0, "mingw32-gcc.exe"},
75 {CC_INTEL, "Intel(R) C++ Compiler for 32-bit applications", 0, "icl.exe"}, // xilink.exe, xilink5.exe, xilink6.exe, xilib.exe
76 {CC_MSVC6, "Microsoft (R) 32-bit C/C++ Optimizing Compiler (6.x)", "Software\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++\\ProductDir", "cl.exe"}, // link.exe, lib.exe
77 {CC_NET2002, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2002 (7.0)", "Software\\Microsoft\\VisualStudio\\7.0\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
78 {CC_NET2003, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2003 (7.1)", "Software\\Microsoft\\VisualStudio\\7.1\\Setup\\VC\\ProductDir", "cl.exe"}, // link.exe, lib.exe
79 {CC_NET2005, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2005 (8.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\8.0", "cl.exe"}, // link.exe, lib.exe
80 {CC_NET2008, "Microsoft (R) 32-bit C/C++ Optimizing Compiler.NET 2008 (9.0)", "Software\\Microsoft\\VisualStudio\\SxS\\VC7\\9.0", "cl.exe"}, // link.exe, lib.exe
81 {CC_UNKNOWN, "Unknown", 0, 0},
82};
83
84
85// Initialize static variables
86Compiler Environment::detectedCompiler = CC_UNKNOWN;
87
88/*!
89 Returns the pointer to the CompilerInfo for a \a compiler.
90*/
91CompilerInfo *Environment::compilerInfo(Compiler compiler)
92{
93 int i = 0;
94 while(compiler_info[i].compiler != compiler && compiler_info[i].compiler != CC_UNKNOWN)
95 ++i;
96 return &(compiler_info[i]);
97}
98
99/*!
100 Returns the path part of a registry key.
101 Ei.
102 For a key
103 "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
104 it returns
105 "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
106*/
107QString Environment::keyPath(const QString &rKey)
108{
109 int idx = rKey.lastIndexOf(QLatin1Char('\\'));
110 if (idx == -1)
111 return QString();
112 return rKey.left(idx + 1);
113}
114
115/*!
116 Returns the name part of a registry key.
117 Ei.
118 For a key
119 "Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
120 it returns
121 "ProductDir"
122*/
123QString Environment::keyName(const QString &rKey)
124{
125 int idx = rKey.lastIndexOf(QLatin1Char('\\'));
126 if (idx == -1)
127 return rKey;
128
129 QString res(rKey.mid(idx + 1));
130 if (res == "Default" || res == ".")
131 res = "";
132 return res;
133}
134
135/*!
136 Returns a registry keys value in string form.
137 If the registry key does not exist, or cannot be accessed, a
138 QString() is returned.
139*/
140QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey)
141{
142#ifndef Q_OS_WIN32
143 return QString();
144#else
145 QString rSubkeyName = keyName(rSubkey);
146 QString rSubkeyPath = keyPath(rSubkey);
147
148 HKEY handle = 0;
149 LONG res;
150 QT_WA( {
151 res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(),
152 0, KEY_READ, &handle);
153 } , {
154 res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(),
155 0, KEY_READ, &handle);
156 } );
157
158 if (res != ERROR_SUCCESS)
159 return QString();
160
161 // get the size and type of the value
162 DWORD dataType;
163 DWORD dataSize;
164 QT_WA( {
165 res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
166 }, {
167 res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize);
168 } );
169 if (res != ERROR_SUCCESS) {
170 RegCloseKey(handle);
171 return QString();
172 }
173
174 // get the value
175 QByteArray data(dataSize, 0);
176 QT_WA( {
177 res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0,
178 reinterpret_cast<unsigned char*>(data.data()), &dataSize);
179 }, {
180 res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0,
181 reinterpret_cast<unsigned char*>(data.data()), &dataSize);
182 } );
183 if (res != ERROR_SUCCESS) {
184 RegCloseKey(handle);
185 return QString();
186 }
187
188 QString result;
189 switch (dataType) {
190 case REG_EXPAND_SZ:
191 case REG_SZ: {
192 QT_WA( {
193 result = QString::fromUtf16(((const ushort*)data.constData()));
194 }, {
195 result = QString::fromLatin1(data.constData());
196 } );
197 break;
198 }
199
200 case REG_MULTI_SZ: {
201 QStringList l;
202 int i = 0;
203 for (;;) {
204 QString s;
205 QT_WA( {
206 s = QString::fromUtf16((const ushort*)data.constData() + i);
207 }, {
208 s = QString::fromLatin1(data.constData() + i);
209 } );
210 i += s.length() + 1;
211
212 if (s.isEmpty())
213 break;
214 l.append(s);
215 }
216 result = l.join(", ");
217 break;
218 }
219
220 case REG_NONE:
221 case REG_BINARY: {
222 QT_WA( {
223 result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2);
224 }, {
225 result = QString::fromLatin1(data.constData(), data.size());
226 } );
227 break;
228 }
229
230 case REG_DWORD_BIG_ENDIAN:
231 case REG_DWORD: {
232 Q_ASSERT(data.size() == sizeof(int));
233 int i;
234 memcpy((char*)&i, data.constData(), sizeof(int));
235 result = QString::number(i);
236 break;
237 }
238
239 default:
240 qWarning("QSettings: unknown data %d type in windows registry", dataType);
241 break;
242 }
243
244 RegCloseKey(handle);
245 return result;
246#endif
247}
248
249/*!
250 Returns the qmakespec for the compiler detected on the system.
251*/
252QString Environment::detectQMakeSpec()
253{
254 QString spec;
255 switch (detectCompiler()) {
256 case CC_NET2008:
257 spec = "win32-msvc2008";
258 break;
259 case CC_NET2005:
260 spec = "win32-msvc2005";
261 break;
262 case CC_NET2003:
263 spec = "win32-msvc2003";
264 break;
265 case CC_NET2002:
266 spec = "win32-msvc2002";
267 break;
268 case CC_MSVC4:
269 case CC_MSVC5:
270 case CC_MSVC6:
271 spec = "win32-msvc";
272 break;
273 case CC_INTEL:
274 spec = "win32-icc";
275 break;
276 case CC_MINGW:
277 spec = "win32-g++";
278 break;
279 case CC_BORLAND:
280 spec = "win32-borland";
281 break;
282 default:
283 break;
284 }
285
286 return spec;
287}
288
289/*!
290 Returns the enum of the compiler which was detected on the system.
291 The compilers are detected in the order as entered into the
292 compiler_info list.
293
294 If more than one compiler is found, CC_UNKNOWN is returned.
295*/
296Compiler Environment::detectCompiler()
297{
298#ifndef Q_OS_WIN32
299 return MSVC6; // Always generate MSVC 6.0 versions on other platforms
300#else
301 if(detectedCompiler != CC_UNKNOWN)
302 return detectedCompiler;
303
304 int installed = 0;
305
306 // Check for compilers in registry first, to see which version is in PATH
307 QString paths = qgetenv("PATH");
308 QStringList pathlist = paths.toLower().split(";");
309 for(int i = 0; compiler_info[i].compiler; ++i) {
310 QString productPath = readRegistryKey(HKEY_LOCAL_MACHINE, compiler_info[i].regKey).toLower();
311 if (productPath.length()) {
312 QStringList::iterator it;
313 for(it = pathlist.begin(); it != pathlist.end(); ++it) {
314 if((*it).contains(productPath)) {
315 ++installed;
316 detectedCompiler = compiler_info[i].compiler;
317 break;
318 }
319 }
320 }
321 }
322
323 // Now just go looking for the executables, and accept any executable as the lowest version
324 if (!installed) {
325 for(int i = 0; compiler_info[i].compiler; ++i) {
326 QString executable = QString(compiler_info[i].executable).toLower();
327 if (executable.length() && Environment::detectExecutable(executable)) {
328 ++installed;
329 detectedCompiler = compiler_info[i].compiler;
330 break;
331 }
332 }
333 }
334
335 if (installed > 1) {
336 cout << "Found more than one known compiler! Using \"" << compilerInfo(detectedCompiler)->compilerStr << "\"" << endl;
337 detectedCompiler = CC_UNKNOWN;
338 }
339 return detectedCompiler;
340#endif
341};
342
343/*!
344 Returns true if the \a executable could be loaded, else false.
345 This means that the executable either is in the current directory
346 or in the PATH.
347*/
348bool Environment::detectExecutable(const QString &executable)
349{
350 PROCESS_INFORMATION procInfo;
351 memset(&procInfo, 0, sizeof(procInfo));
352
353 bool couldExecute;
354 QT_WA({
355 // Unicode version
356 STARTUPINFOW startInfo;
357 memset(&startInfo, 0, sizeof(startInfo));
358 startInfo.cb = sizeof(startInfo);
359
360 couldExecute = CreateProcessW(0, (WCHAR*)executable.utf16(),
361 0, 0, false,
362 CREATE_NO_WINDOW | CREATE_SUSPENDED,
363 0, 0, &startInfo, &procInfo);
364
365 }, {
366 // Ansi version
367 STARTUPINFOA startInfo;
368 memset(&startInfo, 0, sizeof(startInfo));
369 startInfo.cb = sizeof(startInfo);
370
371 couldExecute = CreateProcessA(0, executable.toLocal8Bit().data(),
372 0, 0, false,
373 CREATE_NO_WINDOW | CREATE_SUSPENDED,
374 0, 0, &startInfo, &procInfo);
375 })
376
377 if (couldExecute) {
378 CloseHandle(procInfo.hThread);
379 TerminateProcess(procInfo.hProcess, 0);
380 CloseHandle(procInfo.hProcess);
381 }
382 return couldExecute;
383}
384
385/*!
386 Creates a commandling from \a program and it \a arguments,
387 escaping characters that needs it.
388*/
389static QString qt_create_commandline(const QString &program, const QStringList &arguments)
390{
391 QString programName = program;
392 if (!programName.startsWith("\"") && !programName.endsWith("\"") && programName.contains(" "))
393 programName = "\"" + programName + "\"";
394 programName.replace("/", "\\");
395
396 QString args;
397 // add the prgram as the first arrg ... it works better
398 args = programName + " ";
399 for (int i=0; i<arguments.size(); ++i) {
400 QString tmp = arguments.at(i);
401 // in the case of \" already being in the string the \ must also be escaped
402 tmp.replace( "\\\"", "\\\\\"" );
403 // escape a single " because the arguments will be parsed
404 tmp.replace( "\"", "\\\"" );
405 if (tmp.isEmpty() || tmp.contains(' ') || tmp.contains('\t')) {
406 // The argument must not end with a \ since this would be interpreted
407 // as escaping the quote -- rather put the \ behind the quote: e.g.
408 // rather use "foo"\ than "foo\"
409 QString endQuote("\"");
410 int i = tmp.length();
411 while (i>0 && tmp.at(i-1) == '\\') {
412 --i;
413 endQuote += "\\";
414 }
415 args += QString(" \"") + tmp.left(i) + endQuote;
416 } else {
417 args += ' ' + tmp;
418 }
419 }
420 return args;
421}
422
423/*!
424 Creates a QByteArray of the \a environment in either UNICODE or
425 ansi representation.
426*/
427static QByteArray qt_create_environment(const QStringList &environment)
428{
429 QByteArray envlist;
430 if (!environment.isEmpty()) {
431 int pos = 0;
432 // add PATH if necessary (for DLL loading)
433 QByteArray path = qgetenv("PATH");
434 QT_WA({
435 if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty()
436 && !path.isNull()) {
437 QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path));
438 uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
439 envlist.resize(envlist.size() + tmpSize );
440 memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
441 pos += tmpSize;
442 }
443 // add the user environment
444 for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) {
445 QString tmp = *it;
446 uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
447 envlist.resize(envlist.size() + tmpSize);
448 memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
449 pos += tmpSize;
450 }
451 // add the 2 terminating 0 (actually 4, just to be on the safe side)
452 envlist.resize( envlist.size()+4 );
453 envlist[pos++] = 0;
454 envlist[pos++] = 0;
455 envlist[pos++] = 0;
456 envlist[pos++] = 0;
457 }, {
458 if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) {
459 QByteArray tmp = QString("PATH=%1").arg(QString::fromLocal8Bit(path)).toLocal8Bit();
460 uint tmpSize = tmp.length() + 1;
461 envlist.resize(envlist.size() + tmpSize);
462 memcpy(envlist.data()+pos, tmp.data(), tmpSize);
463 pos += tmpSize;
464 }
465 // add the user environment
466 for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++) {
467 QByteArray tmp = (*it).toLocal8Bit();
468 uint tmpSize = tmp.length() + 1;
469 envlist.resize(envlist.size() + tmpSize);
470 memcpy(envlist.data()+pos, tmp.data(), tmpSize);
471 pos += tmpSize;
472 }
473 // add the terminating 0 (actually 2, just to be on the safe side)
474 envlist.resize(envlist.size()+2);
475 envlist[pos++] = 0;
476 envlist[pos++] = 0;
477 })
478 }
479
480 return envlist;
481}
482
483/*!
484 Executes the command described in \a arguments, in the
485 environment inherited from the parent process, with the
486 \a additionalEnv settings applied.
487 \a removeEnv removes the specified environment variables from
488 the environment of the executed process.
489
490 Returns the exit value of the process, or -1 if the command could
491 not be executed.
492
493 This function uses _(w)spawnvpe to spawn a process by searching
494 through the PATH environment variable.
495*/
496int Environment::execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv)
497{
498#ifdef CONFIGURE_DEBUG_EXECUTE
499 qDebug() << "About to Execute: " << arguments;
500 qDebug() << " " << QDir::currentPath();
501 qDebug() << " " << additionalEnv;
502 qDebug() << " " << removeEnv;
503#endif
504// GetEnvironmentStrings is defined to GetEnvironmentStringsW when
505// UNICODE is defined. We cannot use that, since we need to
506// destinguish between unicode and ansi versions of the functions.
507#if defined(UNICODE) && defined(GetEnvironmentStrings)
508#undef GetEnvironmentStrings
509#endif
510
511 // Create the full environment from the current environment and
512 // the additionalEnv strings, then remove all variables defined
513 // in removeEnv
514 QMap<QString, QString> fullEnvMap;
515 QT_WA({
516 LPWSTR envStrings = GetEnvironmentStringsW();
517 if (envStrings) {
518 int strLen = 0;
519 for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) {
520 strLen = wcslen(envString);
521 QString str = QString((const QChar*)envString, strLen);
522 if (!str.startsWith("=")) { // These are added by the system
523 int sepIndex = str.indexOf('=');
524 fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
525 }
526 }
527 }
528 FreeEnvironmentStringsW(envStrings);
529 }, {
530 LPSTR envStrings = GetEnvironmentStrings();
531 if (envStrings) {
532 int strLen = 0;
533 for (LPSTR envString = envStrings; *(envString); envString += strLen + 1) {
534 strLen = strlen(envString);
535 QString str = QLatin1String(envString);
536 if (!str.startsWith("=")) { // These are added by the system
537 int sepIndex = str.indexOf('=');
538 fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
539 }
540 }
541 }
542 FreeEnvironmentStringsA(envStrings);
543 })
544 // Add additionalEnv variables
545 for (int i = 0; i < additionalEnv.count(); ++i) {
546 const QString &str = additionalEnv.at(i);
547 int sepIndex = str.indexOf('=');
548 fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1));
549 }
550
551 // Remove removeEnv variables
552 for (int j = 0; j < removeEnv.count(); ++j)
553 fullEnvMap.remove(removeEnv.at(j).toUpper());
554
555 // Add all variables to a QStringList
556 QStringList fullEnv;
557 QMapIterator<QString, QString> it(fullEnvMap);
558 while (it.hasNext()) {
559 it.next();
560 fullEnv += QString(it.key() + "=" + it.value());
561 }
562
563 // ----------------------------
564 QString program = arguments.takeAt(0);
565 QString args = qt_create_commandline(program, arguments);
566 QByteArray envlist = qt_create_environment(fullEnv);
567
568 DWORD exitCode = -1;
569 PROCESS_INFORMATION procInfo;
570 memset(&procInfo, 0, sizeof(procInfo));
571
572 bool couldExecute;
573 QT_WA({
574 // Unicode version
575 STARTUPINFOW startInfo;
576 memset(&startInfo, 0, sizeof(startInfo));
577 startInfo.cb = sizeof(startInfo);
578
579 couldExecute = CreateProcessW(0, (WCHAR*)args.utf16(),
580 0, 0, true, CREATE_UNICODE_ENVIRONMENT,
581 envlist.isEmpty() ? 0 : envlist.data(),
582 0, &startInfo, &procInfo);
583 }, {
584 // Ansi version
585 STARTUPINFOA startInfo;
586 memset(&startInfo, 0, sizeof(startInfo));
587 startInfo.cb = sizeof(startInfo);
588
589 couldExecute = CreateProcessA(0, args.toLocal8Bit().data(),
590 0, 0, true, 0,
591 envlist.isEmpty() ? 0 : envlist.data(),
592 0, &startInfo, &procInfo);
593 })
594
595 if (couldExecute) {
596 WaitForSingleObject(procInfo.hProcess, INFINITE);
597 GetExitCodeProcess(procInfo.hProcess, &exitCode);
598 CloseHandle(procInfo.hThread);
599 CloseHandle(procInfo.hProcess);
600 }
601
602
603 if (exitCode == -1) {
604 switch(GetLastError()) {
605 case E2BIG:
606 cerr << "execute: Argument list exceeds 1024 bytes" << endl;
607 foreach(QString arg, arguments)
608 cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
609 break;
610 case ENOENT:
611 cerr << "execute: File or path is not found (" << program.toLocal8Bit().constData() << ")" << endl;
612 break;
613 case ENOEXEC:
614 cerr << "execute: Specified file is not executable or has invalid executable-file format (" << program.toLocal8Bit().constData() << ")" << endl;
615 break;
616 case ENOMEM:
617 cerr << "execute: Not enough memory is available to execute new process." << endl;
618 break;
619 default:
620 cerr << "execute: Unknown error" << endl;
621 foreach(QString arg, arguments)
622 cerr << " (" << arg.toLocal8Bit().constData() << ")" << endl;
623 break;
624 }
625 }
626 return exitCode;
627}
628
629bool Environment::cpdir(const QString &srcDir, const QString &destDir)
630{
631 QString cleanSrcName = QDir::cleanPath(srcDir);
632 QString cleanDstName = QDir::cleanPath(destDir);
633#ifdef CONFIGURE_DEBUG_CP_DIR
634 qDebug() << "Attempt to cpdir " << cleanSrcName << "->" << cleanDstName;
635#endif
636 if(!QFile::exists(cleanDstName) && !QDir().mkpath(cleanDstName)) {
637 qDebug() << "cpdir: Failure to create " << cleanDstName;
638 return false;
639 }
640
641 bool result = true;
642 QDir dir = QDir(cleanSrcName);
643 QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
644 for (int i = 0; result && (i < allEntries.count()); ++i) {
645 QFileInfo entry = allEntries.at(i);
646 bool intermediate = true;
647 if (entry.isDir()) {
648 intermediate = cpdir(QString("%1/%2").arg(cleanSrcName).arg(entry.fileName()),
649 QString("%1/%2").arg(cleanDstName).arg(entry.fileName()));
650 } else {
651 QString destFile = QString("%1/%2").arg(cleanDstName).arg(entry.fileName());
652#ifdef CONFIGURE_DEBUG_CP_DIR
653 qDebug() << "About to cp (file)" << entry.absoluteFilePath() << "->" << destFile;
654#endif
655 QFile::remove(destFile);
656 intermediate = QFile::copy(entry.absoluteFilePath(), destFile);
657 SetFileAttributesA(destFile.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL);
658 }
659 if(!intermediate) {
660 qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir();
661 result = false;
662 }
663 }
664 return result;
665}
666
667bool Environment::rmdir(const QString &name)
668{
669 bool result = true;
670 QString cleanName = QDir::cleanPath(name);
671
672 QDir dir = QDir(cleanName);
673 QFileInfoList allEntries = dir.entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
674 for (int i = 0; result && (i < allEntries.count()); ++i) {
675 QFileInfo entry = allEntries.at(i);
676 if (entry.isDir()) {
677 result &= rmdir(entry.absoluteFilePath());
678 } else {
679 result &= QFile::remove(entry.absoluteFilePath());
680 }
681 }
682 result &= dir.rmdir(cleanName);
683 return result;
684}
685
686QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.