SystemTools.cxx 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
  5. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  8. PURPOSE. See the above copyright notices for more information.
  9. =========================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(SystemTools.hxx)
  12. #include KWSYS_HEADER(Directory.hxx)
  13. #include KWSYS_HEADER(ios/iostream)
  14. #include KWSYS_HEADER(ios/fstream)
  15. #include KWSYS_HEADER(ios/sstream)
  16. #ifdef _MSC_VER
  17. # pragma warning (disable: 4786)
  18. #endif
  19. #include <stdio.h>
  20. #include <sys/stat.h>
  21. #include <ctype.h>
  22. #include <errno.h>
  23. #include <time.h>
  24. // support for realpath call
  25. #ifndef _WIN32
  26. #include <limits.h>
  27. #include <stdlib.h>
  28. #include <sys/param.h>
  29. #include <sys/wait.h>
  30. #include <sys/ioctl.h>
  31. #include <unistd.h>
  32. #include <termios.h>
  33. #endif
  34. #if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__))
  35. #include <io.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <windows.h>
  40. #include <direct.h>
  41. #define _unlink unlink
  42. inline int Mkdir(const char* dir)
  43. {
  44. return _mkdir(dir);
  45. }
  46. inline int Rmdir(const char* dir)
  47. {
  48. return _rmdir(dir);
  49. }
  50. inline const char* Getcwd(char* buf, unsigned int len)
  51. {
  52. return _getcwd(buf, len);
  53. }
  54. inline int Chdir(const char* dir)
  55. {
  56. #if defined(__BORLANDC__)
  57. return chdir(dir);
  58. #else
  59. return _chdir(dir);
  60. #endif
  61. }
  62. inline char *Realpath(const char *path, char *resolved_path)
  63. {
  64. char *ptemp;
  65. char fullpath[MAX_PATH];
  66. if( GetFullPathName(path, sizeof(fullpath), fullpath, &ptemp) )
  67. {
  68. return strcpy(resolved_path, fullpath);
  69. }
  70. return 0;
  71. }
  72. #else
  73. #include <sys/types.h>
  74. #include <fcntl.h>
  75. #include <unistd.h>
  76. inline int Mkdir(const char* dir)
  77. {
  78. return mkdir(dir, 00777);
  79. }
  80. inline int Rmdir(const char* dir)
  81. {
  82. return rmdir(dir);
  83. }
  84. inline const char* Getcwd(char* buf, unsigned int len)
  85. {
  86. return getcwd(buf, len);
  87. }
  88. inline int Chdir(const char* dir)
  89. {
  90. return chdir(dir);
  91. }
  92. inline char *Realpath(const char *path, char *resolved_path)
  93. {
  94. return realpath(path, resolved_path);
  95. }
  96. #endif
  97. #if !defined(_WIN32) && defined(__COMO__)
  98. // Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
  99. extern "C"
  100. {
  101. extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
  102. extern int pclose (FILE *__stream) __THROW;
  103. extern char *realpath (__const char *__restrict __name,
  104. char *__restrict __resolved) __THROW;
  105. extern char *strdup (__const char *__s) __THROW;
  106. extern int putenv (char *__string) __THROW;
  107. }
  108. #endif
  109. /* Implement floattime() for various platforms */
  110. // Taken from Python 2.1.3
  111. #if defined( _WIN32 ) && !defined( __CYGWIN__ )
  112. # include <sys/timeb.h>
  113. # define HAVE_FTIME
  114. # if defined( __BORLANDC__)
  115. # define FTIME ftime
  116. # define TIMEB timeb
  117. # else // Visual studio?
  118. # define FTIME _ftime
  119. # define TIMEB _timeb
  120. # endif
  121. #elif defined( __CYGWIN__ ) || defined( __linux__ )
  122. # include <sys/time.h>
  123. # include <time.h>
  124. # define HAVE_GETTIMEOFDAY
  125. #endif
  126. namespace KWSYS_NAMESPACE
  127. {
  128. class SystemToolsTranslationMap :
  129. public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
  130. {
  131. };
  132. double
  133. SystemTools::GetTime(void)
  134. {
  135. /* There are three ways to get the time:
  136. (1) gettimeofday() -- resolution in microseconds
  137. (2) ftime() -- resolution in milliseconds
  138. (3) time() -- resolution in seconds
  139. In all cases the return value is a float in seconds.
  140. Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may
  141. fail, so we fall back on ftime() or time().
  142. Note: clock resolution does not imply clock accuracy! */
  143. #ifdef HAVE_GETTIMEOFDAY
  144. {
  145. struct timeval t;
  146. #ifdef GETTIMEOFDAY_NO_TZ
  147. if (gettimeofday(&t) == 0)
  148. return (double)t.tv_sec + t.tv_usec*0.000001;
  149. #else /* !GETTIMEOFDAY_NO_TZ */
  150. if (gettimeofday(&t, (struct timezone *)NULL) == 0)
  151. return (double)t.tv_sec + t.tv_usec*0.000001;
  152. #endif /* !GETTIMEOFDAY_NO_TZ */
  153. }
  154. #endif /* !HAVE_GETTIMEOFDAY */
  155. {
  156. #if defined(HAVE_FTIME)
  157. struct TIMEB t;
  158. ::FTIME(&t);
  159. return (double)t.time + (double)t.millitm * (double)0.001;
  160. #else /* !HAVE_FTIME */
  161. time_t secs;
  162. time(&secs);
  163. return (double)secs;
  164. #endif /* !HAVE_FTIME */
  165. }
  166. }
  167. // adds the elements of the env variable path to the arg passed in
  168. void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
  169. {
  170. #if defined(_WIN32) && !defined(__CYGWIN__)
  171. const char* pathSep = ";";
  172. #else
  173. const char* pathSep = ":";
  174. #endif
  175. if(!env)
  176. {
  177. env = "PATH";
  178. }
  179. const char* cpathEnv = SystemTools::GetEnv(env);
  180. if ( !cpathEnv )
  181. {
  182. return;
  183. }
  184. kwsys_stl::string pathEnv = cpathEnv;
  185. // A hack to make the below algorithm work.
  186. if(pathEnv[pathEnv.length()-1] != ':')
  187. {
  188. pathEnv += pathSep;
  189. }
  190. kwsys_stl::string::size_type start =0;
  191. bool done = false;
  192. while(!done)
  193. {
  194. kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
  195. if(endpos != kwsys_stl::string::npos)
  196. {
  197. path.push_back(pathEnv.substr(start, endpos-start));
  198. start = endpos+1;
  199. }
  200. else
  201. {
  202. done = true;
  203. }
  204. }
  205. for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
  206. i != path.end(); ++i)
  207. {
  208. SystemTools::ConvertToUnixSlashes(*i);
  209. }
  210. }
  211. const char* SystemTools::GetEnv(const char* key)
  212. {
  213. return getenv(key);
  214. }
  215. bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
  216. {
  217. const char* v = getenv(key);
  218. if(v)
  219. {
  220. result = v;
  221. return true;
  222. }
  223. else
  224. {
  225. return false;
  226. }
  227. }
  228. const char* SystemTools::GetExecutableExtension()
  229. {
  230. #if defined(_WIN32) || defined(__CYGWIN__)
  231. return ".exe";
  232. #else
  233. return "";
  234. #endif
  235. }
  236. bool SystemTools::MakeDirectory(const char* path)
  237. {
  238. if(SystemTools::FileExists(path))
  239. {
  240. return true;
  241. }
  242. kwsys_stl::string dir = path;
  243. if(dir.size() == 0)
  244. {
  245. return false;
  246. }
  247. SystemTools::ConvertToUnixSlashes(dir);
  248. kwsys_stl::string::size_type pos = dir.find(':');
  249. if(pos == kwsys_stl::string::npos)
  250. {
  251. pos = 0;
  252. }
  253. kwsys_stl::string topdir;
  254. while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
  255. {
  256. topdir = dir.substr(0, pos);
  257. Mkdir(topdir.c_str());
  258. pos++;
  259. }
  260. if(dir[dir.size()-1] == '/')
  261. {
  262. topdir = dir.substr(0, dir.size());
  263. }
  264. else
  265. {
  266. topdir = dir;
  267. }
  268. if(Mkdir(topdir.c_str()) != 0)
  269. {
  270. // There is a bug in the Borland Run time library which makes MKDIR
  271. // return EACCES when it should return EEXISTS
  272. // if it is some other error besides directory exists
  273. // then return false
  274. if( (errno != EEXIST)
  275. #ifdef __BORLANDC__
  276. && (errno != EACCES)
  277. #endif
  278. )
  279. {
  280. return false;
  281. }
  282. }
  283. return true;
  284. }
  285. // replace replace with with as many times as it shows up in source.
  286. // write the result into source.
  287. void SystemTools::ReplaceString(kwsys_stl::string& source,
  288. const char* replace,
  289. const char* with)
  290. {
  291. const char *src = source.c_str();
  292. char *searchPos = const_cast<char *>(strstr(src,replace));
  293. // get out quick if string is not found
  294. if (!searchPos)
  295. {
  296. return;
  297. }
  298. // perform replacements until done
  299. size_t replaceSize = strlen(replace);
  300. char *orig = strdup(src);
  301. char *currentPos = orig;
  302. searchPos = searchPos - src + orig;
  303. // initialize the result
  304. source.erase(source.begin(),source.end());
  305. do
  306. {
  307. *searchPos = '\0';
  308. source += currentPos;
  309. currentPos = searchPos + replaceSize;
  310. // replace
  311. source += with;
  312. searchPos = strstr(currentPos,replace);
  313. }
  314. while (searchPos);
  315. // copy any trailing text
  316. source += currentPos;
  317. free(orig);
  318. }
  319. // Read a registry value.
  320. // Example :
  321. // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
  322. // => will return the data of the "default" value of the key
  323. // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
  324. // => will return the data of the "Root" value of the key
  325. #if defined(_WIN32) && !defined(__CYGWIN__)
  326. bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value)
  327. {
  328. kwsys_stl::string primary = key;
  329. kwsys_stl::string second;
  330. kwsys_stl::string valuename;
  331. size_t start = primary.find("\\");
  332. if (start == kwsys_stl::string::npos)
  333. {
  334. return false;
  335. }
  336. size_t valuenamepos = primary.find(";");
  337. if (valuenamepos != kwsys_stl::string::npos)
  338. {
  339. valuename = primary.substr(valuenamepos+1);
  340. }
  341. second = primary.substr(start+1, valuenamepos-start-1);
  342. primary = primary.substr(0, start);
  343. HKEY primaryKey = HKEY_CURRENT_USER;
  344. if (primary == "HKEY_CURRENT_USER")
  345. {
  346. primaryKey = HKEY_CURRENT_USER;
  347. }
  348. if (primary == "HKEY_CURRENT_CONFIG")
  349. {
  350. primaryKey = HKEY_CURRENT_CONFIG;
  351. }
  352. if (primary == "HKEY_CLASSES_ROOT")
  353. {
  354. primaryKey = HKEY_CLASSES_ROOT;
  355. }
  356. if (primary == "HKEY_LOCAL_MACHINE")
  357. {
  358. primaryKey = HKEY_LOCAL_MACHINE;
  359. }
  360. if (primary == "HKEY_USERS")
  361. {
  362. primaryKey = HKEY_USERS;
  363. }
  364. HKEY hKey;
  365. if(RegOpenKeyEx(primaryKey,
  366. second.c_str(),
  367. 0,
  368. KEY_READ,
  369. &hKey) != ERROR_SUCCESS)
  370. {
  371. return false;
  372. }
  373. else
  374. {
  375. DWORD dwType, dwSize;
  376. dwSize = 1023;
  377. char data[1024];
  378. if(RegQueryValueEx(hKey,
  379. (LPTSTR)valuename.c_str(),
  380. NULL,
  381. &dwType,
  382. (BYTE *)data,
  383. &dwSize) == ERROR_SUCCESS)
  384. {
  385. if (dwType == REG_SZ)
  386. {
  387. value = data;
  388. RegCloseKey(hKey);
  389. return true;
  390. }
  391. }
  392. }
  393. return false;
  394. }
  395. #else
  396. bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &)
  397. {
  398. return false;
  399. }
  400. #endif
  401. // Write a registry value.
  402. // Example :
  403. // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
  404. // => will set the data of the "default" value of the key
  405. // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
  406. // => will set the data of the "Root" value of the key
  407. #if defined(_WIN32) && !defined(__CYGWIN__)
  408. bool SystemTools::WriteRegistryValue(const char *key, const char *value)
  409. {
  410. kwsys_stl::string primary = key;
  411. kwsys_stl::string second;
  412. kwsys_stl::string valuename;
  413. size_t start = primary.find("\\");
  414. if (start == kwsys_stl::string::npos)
  415. {
  416. return false;
  417. }
  418. size_t valuenamepos = primary.find(";");
  419. if (valuenamepos != kwsys_stl::string::npos)
  420. {
  421. valuename = primary.substr(valuenamepos+1);
  422. }
  423. second = primary.substr(start+1, valuenamepos-start-1);
  424. primary = primary.substr(0, start);
  425. HKEY primaryKey = HKEY_CURRENT_USER;
  426. if (primary == "HKEY_CURRENT_USER")
  427. {
  428. primaryKey = HKEY_CURRENT_USER;
  429. }
  430. if (primary == "HKEY_CURRENT_CONFIG")
  431. {
  432. primaryKey = HKEY_CURRENT_CONFIG;
  433. }
  434. if (primary == "HKEY_CLASSES_ROOT")
  435. {
  436. primaryKey = HKEY_CLASSES_ROOT;
  437. }
  438. if (primary == "HKEY_LOCAL_MACHINE")
  439. {
  440. primaryKey = HKEY_LOCAL_MACHINE;
  441. }
  442. if (primary == "HKEY_USERS")
  443. {
  444. primaryKey = HKEY_USERS;
  445. }
  446. HKEY hKey;
  447. DWORD dwDummy;
  448. if(RegCreateKeyEx(primaryKey,
  449. second.c_str(),
  450. 0,
  451. "",
  452. REG_OPTION_NON_VOLATILE,
  453. KEY_WRITE,
  454. NULL,
  455. &hKey,
  456. &dwDummy) != ERROR_SUCCESS)
  457. {
  458. return false;
  459. }
  460. if(RegSetValueEx(hKey,
  461. (LPTSTR)valuename.c_str(),
  462. 0,
  463. REG_SZ,
  464. (CONST BYTE *)value,
  465. (DWORD)(strlen(value) + 1)) == ERROR_SUCCESS)
  466. {
  467. return true;
  468. }
  469. return false;
  470. }
  471. #else
  472. bool SystemTools::WriteRegistryValue(const char *, const char *)
  473. {
  474. return false;
  475. }
  476. #endif
  477. // Delete a registry value.
  478. // Example :
  479. // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
  480. // => will delete the data of the "default" value of the key
  481. // HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
  482. // => will delete the data of the "Root" value of the key
  483. #if defined(_WIN32) && !defined(__CYGWIN__)
  484. bool SystemTools::DeleteRegistryValue(const char *key)
  485. {
  486. kwsys_stl::string primary = key;
  487. kwsys_stl::string second;
  488. kwsys_stl::string valuename;
  489. size_t start = primary.find("\\");
  490. if (start == kwsys_stl::string::npos)
  491. {
  492. return false;
  493. }
  494. size_t valuenamepos = primary.find(";");
  495. if (valuenamepos != kwsys_stl::string::npos)
  496. {
  497. valuename = primary.substr(valuenamepos+1);
  498. }
  499. second = primary.substr(start+1, valuenamepos-start-1);
  500. primary = primary.substr(0, start);
  501. HKEY primaryKey = HKEY_CURRENT_USER;
  502. if (primary == "HKEY_CURRENT_USER")
  503. {
  504. primaryKey = HKEY_CURRENT_USER;
  505. }
  506. if (primary == "HKEY_CURRENT_CONFIG")
  507. {
  508. primaryKey = HKEY_CURRENT_CONFIG;
  509. }
  510. if (primary == "HKEY_CLASSES_ROOT")
  511. {
  512. primaryKey = HKEY_CLASSES_ROOT;
  513. }
  514. if (primary == "HKEY_LOCAL_MACHINE")
  515. {
  516. primaryKey = HKEY_LOCAL_MACHINE;
  517. }
  518. if (primary == "HKEY_USERS")
  519. {
  520. primaryKey = HKEY_USERS;
  521. }
  522. HKEY hKey;
  523. if(RegOpenKeyEx(primaryKey,
  524. second.c_str(),
  525. 0,
  526. KEY_WRITE,
  527. &hKey) != ERROR_SUCCESS)
  528. {
  529. return false;
  530. }
  531. else
  532. {
  533. if(RegDeleteValue(hKey,
  534. (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
  535. {
  536. RegCloseKey(hKey);
  537. return true;
  538. }
  539. }
  540. return false;
  541. }
  542. #else
  543. bool SystemTools::DeleteRegistryValue(const char *)
  544. {
  545. return false;
  546. }
  547. #endif
  548. bool SystemTools::SameFile(const char* file1, const char* file2)
  549. {
  550. #ifdef _WIN32
  551. HANDLE hFile1, hFile2;
  552. hFile1 = CreateFile( file1,
  553. GENERIC_READ,
  554. FILE_SHARE_READ ,
  555. NULL,
  556. OPEN_EXISTING,
  557. FILE_FLAG_BACKUP_SEMANTICS,
  558. NULL
  559. );
  560. hFile2 = CreateFile( file2,
  561. GENERIC_READ,
  562. FILE_SHARE_READ,
  563. NULL,
  564. OPEN_EXISTING,
  565. FILE_FLAG_BACKUP_SEMANTICS,
  566. NULL
  567. );
  568. if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
  569. {
  570. if(hFile1 != INVALID_HANDLE_VALUE)
  571. {
  572. CloseHandle(hFile1);
  573. }
  574. if(hFile2 != INVALID_HANDLE_VALUE)
  575. {
  576. CloseHandle(hFile2);
  577. }
  578. return false;
  579. }
  580. BY_HANDLE_FILE_INFORMATION fiBuf1;
  581. BY_HANDLE_FILE_INFORMATION fiBuf2;
  582. GetFileInformationByHandle( hFile1, &fiBuf1 );
  583. GetFileInformationByHandle( hFile2, &fiBuf2 );
  584. CloseHandle(hFile1);
  585. CloseHandle(hFile2);
  586. return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
  587. fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
  588. fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
  589. #else
  590. struct stat fileStat1, fileStat2;
  591. if (stat(file1, &fileStat1) == 0 && stat(file2, &fileStat2) == 0)
  592. {
  593. // see if the files are the same file
  594. // check the device inode and size
  595. if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
  596. memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
  597. fileStat2.st_size == fileStat1.st_size
  598. )
  599. {
  600. return true;
  601. }
  602. }
  603. return false;
  604. #endif
  605. }
  606. // return true if the file exists
  607. bool SystemTools::FileExists(const char* filename)
  608. {
  609. #ifdef _MSC_VER
  610. # define access _access
  611. #endif
  612. #ifndef R_OK
  613. # define R_OK 04
  614. #endif
  615. if ( access(filename, R_OK) != 0 )
  616. {
  617. return false;
  618. }
  619. else
  620. {
  621. return true;
  622. }
  623. }
  624. // Return a capitalized string (i.e the first letter is uppercased, all other
  625. // are lowercased)
  626. kwsys_stl::string SystemTools::Capitalized(const kwsys_stl::string& s)
  627. {
  628. kwsys_stl::string n;
  629. if(s.size() == 0)
  630. {
  631. return n;
  632. }
  633. n.resize(s.size());
  634. n[0] = static_cast<kwsys_stl::string::value_type>(toupper(s[0]));
  635. for (size_t i = 1; i < s.size(); i++)
  636. {
  637. n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
  638. }
  639. return n;
  640. }
  641. // Return a lower case string
  642. kwsys_stl::string SystemTools::LowerCase(const kwsys_stl::string& s)
  643. {
  644. kwsys_stl::string n;
  645. n.resize(s.size());
  646. for (size_t i = 0; i < s.size(); i++)
  647. {
  648. n[i] = static_cast<kwsys_stl::string::value_type>(tolower(s[i]));
  649. }
  650. return n;
  651. }
  652. // Return a lower case string
  653. kwsys_stl::string SystemTools::UpperCase(const kwsys_stl::string& s)
  654. {
  655. kwsys_stl::string n;
  656. n.resize(s.size());
  657. for (size_t i = 0; i < s.size(); i++)
  658. {
  659. n[i] = static_cast<kwsys_stl::string::value_type>(toupper(s[i]));
  660. }
  661. return n;
  662. }
  663. // convert windows slashes to unix slashes
  664. void SystemTools::ConvertToUnixSlashes(kwsys_stl::string& path)
  665. {
  666. kwsys_stl::string::size_type pos = 0;
  667. while((pos = path.find('\\', pos)) != kwsys_stl::string::npos)
  668. {
  669. // make sure we don't convert an escaped space to a unix slash
  670. if(pos < path.size()-2)
  671. {
  672. if(path[pos+1] != ' ')
  673. {
  674. path[pos] = '/';
  675. }
  676. }
  677. pos++;
  678. }
  679. // Remove all // from the path just like most unix shells
  680. int start_find;
  681. #ifdef _WIN32
  682. // However, on windows if the first characters are both slashes,
  683. // then keep them that way, so that network paths can be handled.
  684. start_find = 1;
  685. #else
  686. start_find = 0;
  687. #endif
  688. while((pos = path.find("//", start_find)) != kwsys_stl::string::npos)
  689. {
  690. SystemTools::ReplaceString(path, "//", "/");
  691. }
  692. // remove any trailing slash
  693. if(path.size() > 1 && path[path.size()-1] == '/')
  694. {
  695. path = path.substr(0, path.size()-1);
  696. }
  697. // if there is a tilda ~ then replace it with HOME
  698. if(path.find("~") == 0)
  699. {
  700. if (getenv("HOME"))
  701. {
  702. path = kwsys_stl::string(getenv("HOME")) + path.substr(1);
  703. }
  704. }
  705. }
  706. // change // to /, and escape any spaces in the path
  707. kwsys_stl::string SystemTools::ConvertToUnixOutputPath(const char* path)
  708. {
  709. kwsys_stl::string ret = path;
  710. // remove // except at the beginning might be a cygwin drive
  711. kwsys_stl::string::size_type pos = 1;
  712. while((pos = ret.find("//", pos)) != kwsys_stl::string::npos)
  713. {
  714. ret.erase(pos, 1);
  715. }
  716. // now escape spaces if there is a space in the path
  717. if(ret.find(" ") != kwsys_stl::string::npos)
  718. {
  719. kwsys_stl::string result = "";
  720. char lastch = 1;
  721. for(const char* ch = ret.c_str(); *ch != '\0'; ++ch)
  722. {
  723. // if it is already escaped then don't try to escape it again
  724. if(*ch == ' ' && lastch != '\\')
  725. {
  726. result += '\\';
  727. }
  728. result += *ch;
  729. lastch = *ch;
  730. }
  731. ret = result;
  732. }
  733. return ret;
  734. }
  735. kwsys_stl::string SystemTools::ConvertToOutputPath(const char* path)
  736. {
  737. #if defined(_WIN32) && !defined(__CYGWIN__)
  738. return SystemTools::ConvertToWindowsOutputPath(path);
  739. #else
  740. return SystemTools::ConvertToUnixOutputPath(path);
  741. #endif
  742. }
  743. // remove double slashes not at the start
  744. kwsys_stl::string SystemTools::ConvertToWindowsOutputPath(const char* path)
  745. {
  746. kwsys_stl::string ret = path;
  747. kwsys_stl::string::size_type pos = 0;
  748. // first convert all of the slashes
  749. while((pos = ret.find('/', pos)) != kwsys_stl::string::npos)
  750. {
  751. ret[pos] = '\\';
  752. pos++;
  753. }
  754. // check for really small paths
  755. if(ret.size() < 2)
  756. {
  757. return ret;
  758. }
  759. // now clean up a bit and remove double slashes
  760. // Only if it is not the first position in the path which is a network
  761. // path on windows
  762. pos = 1; // start at position 1
  763. if(ret[0] == '\"')
  764. {
  765. pos = 2; // if the string is already quoted then start at 2
  766. if(ret.size() < 3)
  767. {
  768. return ret;
  769. }
  770. }
  771. while((pos = ret.find("\\\\", pos)) != kwsys_stl::string::npos)
  772. {
  773. ret.erase(pos, 1);
  774. }
  775. // now double quote the path if it has spaces in it
  776. // and is not already double quoted
  777. if(ret.find(" ") != kwsys_stl::string::npos
  778. && ret[0] != '\"')
  779. {
  780. kwsys_stl::string result;
  781. result = "\"" + ret + "\"";
  782. ret = result;
  783. }
  784. return ret;
  785. }
  786. bool SystemTools::CopyFileIfDifferent(const char* source,
  787. const char* destination)
  788. {
  789. if(SystemTools::FilesDiffer(source, destination))
  790. {
  791. return SystemTools::CopyFileAlways(source, destination);
  792. }
  793. return true;
  794. }
  795. bool SystemTools::FilesDiffer(const char* source,
  796. const char* destination)
  797. {
  798. struct stat statSource;
  799. if (stat(source, &statSource) != 0)
  800. {
  801. return true;
  802. }
  803. struct stat statDestination;
  804. if (stat(destination, &statDestination) != 0)
  805. {
  806. return true;
  807. }
  808. if(statSource.st_size != statDestination.st_size)
  809. {
  810. return true;
  811. }
  812. if(statSource.st_size == 0)
  813. {
  814. return false;
  815. }
  816. #if defined(_WIN32) || defined(__CYGWIN__)
  817. kwsys_ios::ifstream finSource(source, (kwsys_ios::ios::binary |
  818. kwsys_ios::ios::in));
  819. kwsys_ios::ifstream finDestination(destination, (kwsys_ios::ios::binary |
  820. kwsys_ios::ios::in));
  821. #else
  822. kwsys_ios::ifstream finSource(source);
  823. kwsys_ios::ifstream finDestination(destination);
  824. #endif
  825. if(!finSource || !finDestination)
  826. {
  827. return true;
  828. }
  829. char* source_buf = new char[statSource.st_size];
  830. char* dest_buf = new char[statSource.st_size];
  831. finSource.read(source_buf, statSource.st_size);
  832. finDestination.read(dest_buf, statSource.st_size);
  833. if(statSource.st_size != static_cast<long>(finSource.gcount()) ||
  834. statSource.st_size != static_cast<long>(finDestination.gcount()))
  835. {
  836. // Failed to read files.
  837. delete [] source_buf;
  838. delete [] dest_buf;
  839. return true;
  840. }
  841. int ret = memcmp((const void*)source_buf,
  842. (const void*)dest_buf,
  843. statSource.st_size);
  844. delete [] dest_buf;
  845. delete [] source_buf;
  846. return ret != 0;
  847. }
  848. /**
  849. * Copy a file named by "source" to the file named by "destination".
  850. */
  851. bool SystemTools::CopyFileAlways(const char* source, const char* destination)
  852. {
  853. // If files are the same do not copy
  854. if ( SystemTools::SameFile(source, destination) )
  855. {
  856. return true;
  857. }
  858. mode_t perm = 0;
  859. bool perms = SystemTools::GetPermissions(source, perm);
  860. const int bufferSize = 4096;
  861. char buffer[bufferSize];
  862. // If destination is a directory, try to create a file with the same
  863. // name as the source in that directory.
  864. kwsys_stl::string new_destination;
  865. if(SystemTools::FileExists(destination) &&
  866. SystemTools::FileIsDirectory(destination))
  867. {
  868. new_destination = destination;
  869. SystemTools::ConvertToUnixSlashes(new_destination);
  870. new_destination += '/';
  871. kwsys_stl::string source_name = source;
  872. new_destination += SystemTools::GetFilenameName(source_name);
  873. destination = new_destination.c_str();
  874. }
  875. // Create destination directory
  876. kwsys_stl::string destination_dir = destination;
  877. destination_dir = SystemTools::GetFilenamePath(destination_dir);
  878. SystemTools::MakeDirectory(destination_dir.c_str());
  879. // Open files
  880. #if defined(_WIN32) || defined(__CYGWIN__)
  881. kwsys_ios::ifstream fin(source,
  882. kwsys_ios::ios::binary | kwsys_ios::ios::in);
  883. #else
  884. kwsys_ios::ifstream fin(source);
  885. #endif
  886. if(!fin)
  887. {
  888. return false;
  889. }
  890. if ( SystemTools::FileExists(destination) && !SystemTools::RemoveFile(destination) )
  891. {
  892. return false;
  893. }
  894. #if defined(_WIN32) || defined(__CYGWIN__)
  895. kwsys_ios::ofstream fout(destination,
  896. kwsys_ios::ios::binary | kwsys_ios::ios::out | kwsys_ios::ios::trunc);
  897. #else
  898. kwsys_ios::ofstream fout(destination,
  899. kwsys_ios::ios::out | kwsys_ios::ios::trunc);
  900. #endif
  901. if(!fout)
  902. {
  903. return false;
  904. }
  905. // This copy loop is very sensitive on certain platforms with
  906. // slightly broken stream libraries (like HPUX). Normally, it is
  907. // incorrect to not check the error condition on the fin.read()
  908. // before using the data, but the fin.gcount() will be zero if an
  909. // error occurred. Therefore, the loop should be safe everywhere.
  910. while(fin)
  911. {
  912. fin.read(buffer, bufferSize);
  913. if(fin.gcount())
  914. {
  915. fout.write(buffer, fin.gcount());
  916. }
  917. }
  918. // Make sure the operating system has finished writing the file
  919. // before closing it. This will ensure the file is finished before
  920. // the check below.
  921. fout.flush();
  922. fin.close();
  923. fout.close();
  924. // More checks.
  925. struct stat statSource, statDestination;
  926. statSource.st_size = 12345;
  927. statDestination.st_size = 12345;
  928. if(stat(source, &statSource) != 0)
  929. {
  930. return false;
  931. }
  932. else if(stat(destination, &statDestination) != 0)
  933. {
  934. return false;
  935. }
  936. else if(statSource.st_size != statDestination.st_size)
  937. {
  938. return false;
  939. }
  940. if ( perms )
  941. {
  942. if ( !SystemTools::SetPermissions(destination, perm) )
  943. {
  944. return false;
  945. }
  946. }
  947. return true;
  948. }
  949. // return size of file; also returns zero if no file exists
  950. unsigned long SystemTools::FileLength(const char* filename)
  951. {
  952. struct stat fs;
  953. if (stat(filename, &fs) != 0)
  954. {
  955. return 0;
  956. }
  957. else
  958. {
  959. return fs.st_size;
  960. }
  961. }
  962. int SystemTools::Strucmp(const char *s1, const char *s2)
  963. {
  964. // lifted from Graphvis http://www.graphviz.org
  965. while ((*s1 != '\0')
  966. && (tolower(*s1) == tolower(*s2)))
  967. {
  968. s1++;
  969. s2++;
  970. }
  971. return tolower(*s1) - tolower(*s2);
  972. }
  973. // return true if the file exists
  974. long int SystemTools::ModifiedTime(const char* filename)
  975. {
  976. struct stat fs;
  977. if (stat(filename, &fs) != 0)
  978. {
  979. return 0;
  980. }
  981. else
  982. {
  983. return (long int)fs.st_mtime;
  984. }
  985. }
  986. kwsys_stl::string SystemTools::GetLastSystemError()
  987. {
  988. int e = errno;
  989. return strerror(e);
  990. }
  991. bool SystemTools::RemoveFile(const char* source)
  992. {
  993. return unlink(source) != 0 ? false : true;
  994. }
  995. bool SystemTools::RemoveADirectory(const char* source)
  996. {
  997. Directory dir;
  998. dir.Load(source);
  999. size_t fileNum;
  1000. for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum)
  1001. {
  1002. if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".") &&
  1003. strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)),".."))
  1004. {
  1005. kwsys_stl::string fullPath = source;
  1006. fullPath += "/";
  1007. fullPath += dir.GetFile(static_cast<unsigned long>(fileNum));
  1008. if(SystemTools::FileIsDirectory(fullPath.c_str()))
  1009. {
  1010. if (!SystemTools::RemoveADirectory(fullPath.c_str()))
  1011. {
  1012. return false;
  1013. }
  1014. }
  1015. else
  1016. {
  1017. if(!SystemTools::RemoveFile(fullPath.c_str()))
  1018. {
  1019. return false;
  1020. }
  1021. }
  1022. }
  1023. }
  1024. return (Rmdir(source) == 0);
  1025. }
  1026. /**
  1027. * Find the file the given name. Searches the given path and then
  1028. * the system search path. Returns the full path to the file if it is
  1029. * found. Otherwise, the empty string is returned.
  1030. */
  1031. kwsys_stl::string SystemTools
  1032. ::FindFile(const char* name,
  1033. const kwsys_stl::vector<kwsys_stl::string>& userPaths)
  1034. {
  1035. // Add the system search path to our path first
  1036. kwsys_stl::vector<kwsys_stl::string> path;
  1037. SystemTools::GetPath(path, "CMAKE_FILE_PATH");
  1038. SystemTools::GetPath(path);
  1039. // now add the additional paths
  1040. path.insert(path.end(), userPaths.begin(), userPaths.end());
  1041. // now look for the file
  1042. kwsys_stl::string tryPath;
  1043. for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
  1044. p != path.end(); ++p)
  1045. {
  1046. tryPath = *p;
  1047. tryPath += "/";
  1048. tryPath += name;
  1049. if(SystemTools::FileExists(tryPath.c_str()) &&
  1050. !SystemTools::FileIsDirectory(tryPath.c_str()))
  1051. {
  1052. return SystemTools::CollapseFullPath(tryPath.c_str());
  1053. }
  1054. }
  1055. // Couldn't find the file.
  1056. return "";
  1057. }
  1058. /**
  1059. * Find the executable with the given name. Searches the given path and then
  1060. * the system search path. Returns the full path to the executable if it is
  1061. * found. Otherwise, the empty string is returned.
  1062. */
  1063. kwsys_stl::string SystemTools::FindProgram(
  1064. const char* name,
  1065. const kwsys_stl::vector<kwsys_stl::string>& userPaths,
  1066. bool no_system_path)
  1067. {
  1068. if(!name)
  1069. {
  1070. return "";
  1071. }
  1072. // See if the executable exists as written.
  1073. if(SystemTools::FileExists(name) &&
  1074. !SystemTools::FileIsDirectory(name))
  1075. {
  1076. return SystemTools::CollapseFullPath(name);
  1077. }
  1078. kwsys_stl::string tryPath = name;
  1079. tryPath += SystemTools::GetExecutableExtension();
  1080. if(SystemTools::FileExists(tryPath.c_str()) &&
  1081. !SystemTools::FileIsDirectory(tryPath.c_str()))
  1082. {
  1083. return SystemTools::CollapseFullPath(tryPath.c_str());
  1084. }
  1085. kwsys_stl::vector<kwsys_stl::string> path;
  1086. SystemTools::GetPath(path, "CMAKE_PROGRAM_PATH");
  1087. // Add the system search path to our path.
  1088. if (!no_system_path)
  1089. {
  1090. SystemTools::GetPath(path);
  1091. }
  1092. // now add the additional paths
  1093. path.insert(path.end(), userPaths.begin(), userPaths.end());
  1094. for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
  1095. p != path.end(); ++p)
  1096. {
  1097. tryPath = *p;
  1098. tryPath += "/";
  1099. tryPath += name;
  1100. if(SystemTools::FileExists(tryPath.c_str()) &&
  1101. !SystemTools::FileIsDirectory(tryPath.c_str()))
  1102. {
  1103. return SystemTools::CollapseFullPath(tryPath.c_str());
  1104. }
  1105. #ifdef _WIN32
  1106. tryPath += ".com";
  1107. if(SystemTools::FileExists(tryPath.c_str()) &&
  1108. !SystemTools::FileIsDirectory(tryPath.c_str()))
  1109. {
  1110. return SystemTools::CollapseFullPath(tryPath.c_str());
  1111. }
  1112. tryPath = *p;
  1113. tryPath += "/";
  1114. tryPath += name;
  1115. #endif
  1116. tryPath += SystemTools::GetExecutableExtension();
  1117. if(SystemTools::FileExists(tryPath.c_str()) &&
  1118. !SystemTools::FileIsDirectory(tryPath.c_str()))
  1119. {
  1120. return SystemTools::CollapseFullPath(tryPath.c_str());
  1121. }
  1122. }
  1123. // Couldn't find the program.
  1124. return "";
  1125. }
  1126. /**
  1127. * Find the library with the given name. Searches the given path and then
  1128. * the system search path. Returns the full path to the library if it is
  1129. * found. Otherwise, the empty string is returned.
  1130. */
  1131. kwsys_stl::string SystemTools
  1132. ::FindLibrary(const char* name,
  1133. const kwsys_stl::vector<kwsys_stl::string>& userPaths)
  1134. {
  1135. // See if the executable exists as written.
  1136. if(SystemTools::FileExists(name) &&
  1137. !SystemTools::FileIsDirectory(name))
  1138. {
  1139. return SystemTools::CollapseFullPath(name);
  1140. }
  1141. // Add the system search path to our path.
  1142. kwsys_stl::vector<kwsys_stl::string> path;
  1143. SystemTools::GetPath(path);
  1144. // now add the additional paths
  1145. path.insert(path.end(), userPaths.begin(), userPaths.end());
  1146. kwsys_stl::string tryPath;
  1147. for(kwsys_stl::vector<kwsys_stl::string>::const_iterator p = path.begin();
  1148. p != path.end(); ++p)
  1149. {
  1150. #if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
  1151. tryPath = *p;
  1152. tryPath += "/";
  1153. tryPath += name;
  1154. tryPath += ".lib";
  1155. if(SystemTools::FileExists(tryPath.c_str())
  1156. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1157. {
  1158. return SystemTools::CollapseFullPath(tryPath.c_str());
  1159. }
  1160. #else
  1161. tryPath = *p;
  1162. tryPath += "/lib";
  1163. tryPath += name;
  1164. tryPath += ".so";
  1165. if(SystemTools::FileExists(tryPath.c_str())
  1166. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1167. {
  1168. return SystemTools::CollapseFullPath(tryPath.c_str());
  1169. }
  1170. tryPath = *p;
  1171. tryPath += "/lib";
  1172. tryPath += name;
  1173. tryPath += ".a";
  1174. if(SystemTools::FileExists(tryPath.c_str())
  1175. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1176. {
  1177. return SystemTools::CollapseFullPath(tryPath.c_str());
  1178. }
  1179. tryPath = *p;
  1180. tryPath += "/lib";
  1181. tryPath += name;
  1182. tryPath += ".sl";
  1183. if(SystemTools::FileExists(tryPath.c_str())
  1184. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1185. {
  1186. return SystemTools::CollapseFullPath(tryPath.c_str());
  1187. }
  1188. tryPath = *p;
  1189. tryPath += "/lib";
  1190. tryPath += name;
  1191. tryPath += ".dylib";
  1192. if(SystemTools::FileExists(tryPath.c_str())
  1193. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1194. {
  1195. return SystemTools::CollapseFullPath(tryPath.c_str());
  1196. }
  1197. tryPath = *p;
  1198. tryPath += "/lib";
  1199. tryPath += name;
  1200. tryPath += ".dll";
  1201. if(SystemTools::FileExists(tryPath.c_str())
  1202. && !SystemTools::FileIsDirectory(tryPath.c_str()))
  1203. {
  1204. return SystemTools::CollapseFullPath(tryPath.c_str());
  1205. }
  1206. #endif
  1207. }
  1208. // Couldn't find the library.
  1209. return "";
  1210. }
  1211. bool SystemTools::FileIsDirectory(const char* name)
  1212. {
  1213. struct stat fs;
  1214. if(stat(name, &fs) == 0)
  1215. {
  1216. #if _WIN32
  1217. return ((fs.st_mode & _S_IFDIR) != 0);
  1218. #else
  1219. return S_ISDIR(fs.st_mode);
  1220. #endif
  1221. }
  1222. else
  1223. {
  1224. return false;
  1225. }
  1226. }
  1227. int SystemTools::ChangeDirectory(const char *dir)
  1228. {
  1229. return Chdir(dir);
  1230. }
  1231. kwsys_stl::string SystemTools::GetCurrentWorkingDirectory()
  1232. {
  1233. char buf[2048];
  1234. const char* cwd = Getcwd(buf, 2048);
  1235. kwsys_stl::string path;
  1236. if ( cwd )
  1237. {
  1238. path = cwd;
  1239. }
  1240. return SystemTools::CollapseFullPath(path.c_str());
  1241. }
  1242. kwsys_stl::string SystemTools::GetProgramPath(const char* in_name)
  1243. {
  1244. kwsys_stl::string dir, file;
  1245. SystemTools::SplitProgramPath(in_name, dir, file);
  1246. return dir;
  1247. }
  1248. bool SystemTools::SplitProgramPath(const char* in_name,
  1249. kwsys_stl::string& dir,
  1250. kwsys_stl::string& file,
  1251. bool)
  1252. {
  1253. dir = in_name;
  1254. file = "";
  1255. SystemTools::ConvertToUnixSlashes(dir);
  1256. if(!SystemTools::FileIsDirectory(dir.c_str()))
  1257. {
  1258. kwsys_stl::string::size_type slashPos = dir.rfind("/");
  1259. if(slashPos != kwsys_stl::string::npos)
  1260. {
  1261. file = dir.substr(slashPos+1);
  1262. dir = dir.substr(0, slashPos);
  1263. }
  1264. else
  1265. {
  1266. file = dir;
  1267. dir = "";
  1268. }
  1269. }
  1270. if(!(dir == "") && !SystemTools::FileIsDirectory(dir.c_str()))
  1271. {
  1272. kwsys_stl::string oldDir = in_name;
  1273. SystemTools::ConvertToUnixSlashes(oldDir);
  1274. dir = in_name;
  1275. return false;
  1276. }
  1277. return true;
  1278. }
  1279. bool SystemTools::FindProgramPath(const char* argv0,
  1280. kwsys_stl::string& pathOut,
  1281. kwsys_stl::string& errorMsg,
  1282. const char* exeName,
  1283. const char* buildDir,
  1284. const char* installPrefix )
  1285. {
  1286. kwsys_stl::vector<kwsys_stl::string> failures;
  1287. kwsys_stl::string self = argv0;
  1288. SystemTools::ConvertToUnixSlashes(self);
  1289. failures.push_back(argv0);
  1290. self = SystemTools::FindProgram(self.c_str());
  1291. if(!SystemTools::FileExists(self.c_str()))
  1292. {
  1293. if(buildDir)
  1294. {
  1295. kwsys_stl::string intdir = ".";
  1296. #ifdef CMAKE_INTDIR
  1297. intdir = CMAKE_INTDIR;
  1298. #endif
  1299. self = buildDir;
  1300. self += "/bin/";
  1301. self += intdir;
  1302. self += "/";
  1303. self += exeName;
  1304. self += SystemTools::GetExecutableExtension();
  1305. }
  1306. }
  1307. if(installPrefix)
  1308. {
  1309. if(!SystemTools::FileExists(self.c_str()))
  1310. {
  1311. failures.push_back(self);
  1312. self = installPrefix;
  1313. self += "/bin/";
  1314. self += exeName;
  1315. }
  1316. }
  1317. if(!SystemTools::FileExists(self.c_str()))
  1318. {
  1319. failures.push_back(self);
  1320. kwsys_ios::ostringstream msg;
  1321. msg << "Can not find the command line program " << exeName << "\n";
  1322. msg << " argv[0] = \"" << argv0 << "\"\n";
  1323. msg << " Attempted paths:\n";
  1324. kwsys_stl::vector<kwsys_stl::string>::iterator i;
  1325. for(i=failures.begin(); i != failures.end(); ++i)
  1326. {
  1327. msg << " \"" << i->c_str() << "\"\n";
  1328. }
  1329. errorMsg = msg.str();
  1330. return false;
  1331. }
  1332. pathOut = self;
  1333. return true;
  1334. }
  1335. kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative)
  1336. {
  1337. return SystemTools::CollapseFullPath(in_relative, 0);
  1338. }
  1339. void SystemTools::AddTranslationPath(const char * a, const char * b)
  1340. {
  1341. kwsys_stl::string path_a = a;
  1342. kwsys_stl::string path_b = b;
  1343. SystemTools::ConvertToUnixSlashes(path_a);
  1344. SystemTools::ConvertToUnixSlashes(path_b);
  1345. // First check this is a directory path, since we don't want the table to
  1346. // grow too fat
  1347. if( SystemTools::FileIsDirectory( path_a.c_str() ) )
  1348. {
  1349. // Make sure the path is a full path and does not contain no '..'
  1350. if( SystemTools::FileIsFullPath(path_b.c_str()) && path_b.find("..")
  1351. == kwsys_stl::string::npos )
  1352. {
  1353. // Before inserting make sure path ends with '/'
  1354. path_a += '/'; path_b += '/';
  1355. if( !(path_a == path_b) )
  1356. {
  1357. SystemTools::TranslationMap->insert(
  1358. SystemToolsTranslationMap::value_type(path_a, path_b));
  1359. }
  1360. }
  1361. }
  1362. }
  1363. void SystemTools::AddKeepPath(const char* dir)
  1364. {
  1365. kwsys_stl::string cdir = SystemTools::CollapseFullPath(dir);
  1366. SystemTools::AddTranslationPath(cdir.c_str(), dir);
  1367. }
  1368. void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
  1369. {
  1370. // In case a file was specified we still have to go through this:
  1371. // Now convert any path found in the table back to the one desired:
  1372. kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>::const_iterator it;
  1373. for(it = SystemTools::TranslationMap->begin();
  1374. it != SystemTools::TranslationMap->end();
  1375. ++it )
  1376. {
  1377. // We need to check of the path is a substring of the other path
  1378. // But also check that the last character is a '/' otherwise we could
  1379. // have some weird case such as /tmp/VTK and /tmp/VTK-bin
  1380. if(path.size() > 1 && path[path.size()-1] != '/')
  1381. {
  1382. // Do not append '/' on a program name:
  1383. if( SystemTools::FileIsDirectory( path.c_str() ) )
  1384. {
  1385. path += "/";
  1386. }
  1387. }
  1388. if(path.find( it->first ) == 0)
  1389. {
  1390. path = path.replace( 0, it->first.size(), it->second);
  1391. }
  1392. }
  1393. }
  1394. kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative,
  1395. const char* in_base)
  1396. {
  1397. static int initialized = 0;
  1398. kwsys_stl::string orig;
  1399. // Change to base of relative path.
  1400. if(in_base)
  1401. {
  1402. // Save original working directory.
  1403. orig = SystemTools::GetCurrentWorkingDirectory();
  1404. Chdir(in_base);
  1405. }
  1406. kwsys_stl::string dir, file;
  1407. SystemTools::SplitProgramPath(in_relative, dir, file, false);
  1408. if(dir.size() == 0 &&
  1409. in_relative && strlen(in_relative) > 0 &&
  1410. in_relative[0] == '/')
  1411. {
  1412. dir = "/";
  1413. }
  1414. # ifdef MAXPATHLEN
  1415. char resolved_name[MAXPATHLEN];
  1416. # else
  1417. # ifdef PATH_MAX
  1418. char resolved_name[PATH_MAX];
  1419. # else
  1420. char resolved_name[5024];
  1421. # endif //PATH_MAX
  1422. # endif //MAXPATHLEN
  1423. // Resolve relative path.
  1424. kwsys_stl::string newDir;
  1425. if(!(dir == ""))
  1426. {
  1427. Realpath(dir.c_str(), resolved_name);
  1428. newDir = resolved_name;
  1429. }
  1430. else
  1431. {
  1432. newDir = SystemTools::GetCurrentWorkingDirectory();
  1433. }
  1434. if(in_base)
  1435. {
  1436. // Restore original working directory.
  1437. Chdir(orig.c_str());
  1438. }
  1439. // Construct and return the full path.
  1440. kwsys_stl::string newPath = newDir;
  1441. if(!(file == ""))
  1442. {
  1443. if(!(newDir.size() == 1 && newDir[0] == '/'))
  1444. {
  1445. newPath += "/";
  1446. }
  1447. newPath += file;
  1448. }
  1449. // If the table has never been initialized, add default path:
  1450. if(!initialized)
  1451. {
  1452. initialized = 1;
  1453. //Also add some good default one:
  1454. // This one should always be there it fix a bug on sgi
  1455. SystemTools::AddTranslationPath("/tmp_mnt/", "/");
  1456. //This is a good default also:
  1457. SystemTools::AddKeepPath("/tmp/");
  1458. }
  1459. // Now we need to update the translation table with this potentially new path
  1460. SystemTools::AddTranslationPath(newPath.c_str(), in_relative);
  1461. SystemTools::CheckTranslationPath(newPath);
  1462. return newPath;
  1463. }
  1464. bool SystemTools::Split(const char* str, kwsys_stl::vector<kwsys_stl::string>& lines)
  1465. {
  1466. kwsys_stl::string data(str);
  1467. kwsys_stl::string::size_type lpos = 0;
  1468. while(lpos < data.length())
  1469. {
  1470. kwsys_stl::string::size_type rpos = data.find_first_of("\n", lpos);
  1471. if(rpos == kwsys_stl::string::npos)
  1472. {
  1473. // Line ends at end of string without a newline.
  1474. lines.push_back(data.substr(lpos));
  1475. return false;
  1476. }
  1477. if((rpos > lpos) && (data[rpos-1] == '\r'))
  1478. {
  1479. // Line ends in a "\r\n" pair, remove both characters.
  1480. lines.push_back(data.substr(lpos, (rpos-1)-lpos));
  1481. }
  1482. else
  1483. {
  1484. // Line ends in a "\n", remove the character.
  1485. lines.push_back(data.substr(lpos, rpos-lpos));
  1486. }
  1487. lpos = rpos+1;
  1488. }
  1489. return true;
  1490. }
  1491. /**
  1492. * Return path of a full filename (no trailing slashes).
  1493. * Warning: returned path is converted to Unix slashes format.
  1494. */
  1495. kwsys_stl::string SystemTools::GetFilenamePath(const kwsys_stl::string& filename)
  1496. {
  1497. kwsys_stl::string fn = filename;
  1498. SystemTools::ConvertToUnixSlashes(fn);
  1499. kwsys_stl::string::size_type slash_pos = fn.rfind("/");
  1500. if(slash_pos != kwsys_stl::string::npos)
  1501. {
  1502. return fn.substr(0, slash_pos);
  1503. }
  1504. else
  1505. {
  1506. return "";
  1507. }
  1508. }
  1509. /**
  1510. * Return file name of a full filename (i.e. file name without path).
  1511. */
  1512. kwsys_stl::string SystemTools::GetFilenameName(const kwsys_stl::string& filename)
  1513. {
  1514. kwsys_stl::string fn = filename;
  1515. SystemTools::ConvertToUnixSlashes(fn);
  1516. kwsys_stl::string::size_type slash_pos = fn.rfind("/");
  1517. if(slash_pos != kwsys_stl::string::npos)
  1518. {
  1519. return fn.substr(slash_pos + 1);
  1520. }
  1521. else
  1522. {
  1523. return filename;
  1524. }
  1525. }
  1526. /**
  1527. * Return file extension of a full filename (dot included).
  1528. * Warning: this is the longest extension (for example: .tar.gz)
  1529. */
  1530. kwsys_stl::string SystemTools::GetFilenameExtension(const kwsys_stl::string& filename)
  1531. {
  1532. kwsys_stl::string name = SystemTools::GetFilenameName(filename);
  1533. kwsys_stl::string::size_type dot_pos = name.find(".");
  1534. if(dot_pos != kwsys_stl::string::npos)
  1535. {
  1536. return name.substr(dot_pos);
  1537. }
  1538. else
  1539. {
  1540. return "";
  1541. }
  1542. }
  1543. /**
  1544. * Return file extension of a full filename (dot included).
  1545. * Warning: this is the shortest extension (for example: .tar.gz)
  1546. */
  1547. kwsys_stl::string SystemTools::GetFilenameLastExtension(const kwsys_stl::string& filename)
  1548. {
  1549. kwsys_stl::string name = SystemTools::GetFilenameName(filename);
  1550. kwsys_stl::string::size_type dot_pos = name.rfind(".");
  1551. if(dot_pos != kwsys_stl::string::npos)
  1552. {
  1553. return name.substr(dot_pos);
  1554. }
  1555. else
  1556. {
  1557. return "";
  1558. }
  1559. }
  1560. /**
  1561. * Return file name without extension of a full filename (i.e. without path).
  1562. * Warning: it considers the longest extension (for example: .tar.gz)
  1563. */
  1564. kwsys_stl::string SystemTools::GetFilenameWithoutExtension(const kwsys_stl::string& filename)
  1565. {
  1566. kwsys_stl::string name = SystemTools::GetFilenameName(filename);
  1567. kwsys_stl::string::size_type dot_pos = name.find(".");
  1568. if(dot_pos != kwsys_stl::string::npos)
  1569. {
  1570. return name.substr(0, dot_pos);
  1571. }
  1572. else
  1573. {
  1574. return name;
  1575. }
  1576. }
  1577. /**
  1578. * Return file name without extension of a full filename (i.e. without path).
  1579. * Warning: it considers the last extension (for example: removes .gz
  1580. * from .tar.gz)
  1581. */
  1582. kwsys_stl::string
  1583. SystemTools::GetFilenameWithoutLastExtension(const kwsys_stl::string& filename)
  1584. {
  1585. kwsys_stl::string name = SystemTools::GetFilenameName(filename);
  1586. kwsys_stl::string::size_type dot_pos = name.rfind(".");
  1587. if(dot_pos != kwsys_stl::string::npos)
  1588. {
  1589. return name.substr(0, dot_pos);
  1590. }
  1591. else
  1592. {
  1593. return name;
  1594. }
  1595. }
  1596. bool SystemTools::FileIsFullPath(const char* in_name)
  1597. {
  1598. kwsys_stl::string name = in_name;
  1599. #if defined(_WIN32) || defined(__CYGWIN__)
  1600. // On Windows, the name must be at least two characters long.
  1601. if(name.length() < 2)
  1602. {
  1603. return false;
  1604. }
  1605. if(name[1] == ':')
  1606. {
  1607. return true;
  1608. }
  1609. if(name[0] == '\\')
  1610. {
  1611. return true;
  1612. }
  1613. #else
  1614. // On UNIX, the name must be at least one character long.
  1615. if(name.length() < 1)
  1616. {
  1617. return false;
  1618. }
  1619. #endif
  1620. // On UNIX, the name must begin in a '/'.
  1621. // On Windows, if the name begins in a '/', then it is a full
  1622. // network path.
  1623. if(name[0] == '/')
  1624. {
  1625. return true;
  1626. }
  1627. return false;
  1628. }
  1629. bool SystemTools::GetShortPath(const char* path, kwsys_stl::string& shortPath)
  1630. {
  1631. #if defined(WIN32) && !defined(__CYGWIN__)
  1632. const int size = int(strlen(path)) +1; // size of return
  1633. char *buffer = new char[size]; // create a buffer
  1634. char *tempPath = new char[size]; // create a buffer
  1635. int ret;
  1636. // if the path passed in has quotes around it, first remove the quotes
  1637. if (path[0] == '"' && path[strlen(path)-1] == '"')
  1638. {
  1639. strcpy(tempPath,path+1);
  1640. tempPath[strlen(tempPath)-1] = '\0';
  1641. }
  1642. else
  1643. {
  1644. strcpy(tempPath,path);
  1645. }
  1646. buffer[0] = 0;
  1647. ret = GetShortPathName(tempPath, buffer, size);
  1648. if(buffer[0] == 0 || ret > size)
  1649. {
  1650. delete [] buffer;
  1651. delete [] tempPath;
  1652. return false;
  1653. }
  1654. else
  1655. {
  1656. shortPath = buffer;
  1657. delete [] buffer;
  1658. delete [] tempPath;
  1659. return true;
  1660. }
  1661. #else
  1662. shortPath = path;
  1663. return true;
  1664. #endif
  1665. }
  1666. void SystemTools::SplitProgramFromArgs(const char* path,
  1667. kwsys_stl::string& program, kwsys_stl::string& args)
  1668. {
  1669. if(SystemTools::FileExists(path))
  1670. {
  1671. program = path;
  1672. args = "";
  1673. return;
  1674. }
  1675. kwsys_stl::vector<kwsys_stl::string> e;
  1676. kwsys_stl::string findProg = SystemTools::FindProgram(path, e);
  1677. if(findProg.size())
  1678. {
  1679. program = findProg;
  1680. args = "";
  1681. return;
  1682. }
  1683. kwsys_stl::string dir = path;
  1684. kwsys_stl::string::size_type spacePos = dir.rfind(' ');
  1685. if(spacePos == kwsys_stl::string::npos)
  1686. {
  1687. program = "";
  1688. args = "";
  1689. return;
  1690. }
  1691. while(spacePos != kwsys_stl::string::npos)
  1692. {
  1693. kwsys_stl::string tryProg = dir.substr(0, spacePos);
  1694. if(SystemTools::FileExists(tryProg.c_str()))
  1695. {
  1696. program = tryProg;
  1697. args = dir.substr(spacePos, dir.size()-spacePos);
  1698. return;
  1699. }
  1700. findProg = SystemTools::FindProgram(tryProg.c_str(), e);
  1701. if(findProg.size())
  1702. {
  1703. program = findProg;
  1704. args = dir.substr(spacePos, dir.size()-spacePos);
  1705. return;
  1706. }
  1707. spacePos = dir.rfind(' ', spacePos--);
  1708. }
  1709. program = "";
  1710. args = "";
  1711. }
  1712. kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
  1713. {
  1714. char buf[1024];
  1715. time_t t;
  1716. time(&t);
  1717. strftime(buf, sizeof(buf), format, localtime(&t));
  1718. return buf;
  1719. }
  1720. kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
  1721. {
  1722. kwsys_stl::string str(s);
  1723. if (str.find_first_of("0123456789") == 0)
  1724. {
  1725. str = "_" + str;
  1726. }
  1727. kwsys_stl::string permited_chars("_"
  1728. "abcdefghijklmnopqrstuvwxyz"
  1729. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1730. "0123456789");
  1731. kwsys_stl::string::size_type pos = 0;
  1732. while ((pos = str.find_first_not_of(permited_chars, pos)) != kwsys_stl::string::npos)
  1733. {
  1734. str[pos] = '_';
  1735. }
  1736. return str;
  1737. }
  1738. // Due to a buggy stream library on the HP and another on Mac OSX, we
  1739. // need this very carefully written version of getline. Returns true
  1740. // if any data were read before the end-of-file was reached.
  1741. bool SystemTools::GetLineFromStream(kwsys_ios::istream& is, kwsys_stl::string& line,
  1742. bool *has_newline /* = 0 */)
  1743. {
  1744. const int bufferSize = 1024;
  1745. char buffer[bufferSize];
  1746. line = "";
  1747. bool haveData = false;
  1748. if ( has_newline )
  1749. {
  1750. *has_newline = false;
  1751. }
  1752. // If no characters are read from the stream, the end of file has
  1753. // been reached.
  1754. while((is.getline(buffer, bufferSize), is.gcount() > 0))
  1755. {
  1756. haveData = true;
  1757. line.append(buffer);
  1758. // If newline character was read, the gcount includes the
  1759. // character, but the buffer does not. The end of line has been
  1760. // reached.
  1761. if(strlen(buffer) < static_cast<size_t>(is.gcount()))
  1762. {
  1763. if ( has_newline )
  1764. {
  1765. *has_newline = true;
  1766. }
  1767. break;
  1768. }
  1769. // The fail bit may be set. Clear it.
  1770. is.clear(is.rdstate() & ~kwsys_ios::ios::failbit);
  1771. }
  1772. return haveData;
  1773. }
  1774. int SystemTools::GetTerminalWidth()
  1775. {
  1776. int width = -1;
  1777. #ifndef _WIN32
  1778. struct winsize ws;
  1779. char *columns; /* Unix98 environment variable */
  1780. if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0)
  1781. {
  1782. width = ws.ws_col;
  1783. }
  1784. if(!isatty(STDOUT_FILENO))
  1785. {
  1786. width = -1;
  1787. }
  1788. columns = getenv("COLUMNS");
  1789. if(columns && *columns)
  1790. {
  1791. long t;
  1792. char *endptr;
  1793. t = strtol(columns, &endptr, 0);
  1794. if(endptr && !*endptr && (t>0) && (t<1000))
  1795. {
  1796. width = (int)t;
  1797. }
  1798. }
  1799. if ( width < 9 )
  1800. {
  1801. width = -1;
  1802. }
  1803. #endif
  1804. return width;
  1805. }
  1806. bool SystemTools::GetPermissions(const char* file, mode_t& mode)
  1807. {
  1808. if ( !file )
  1809. {
  1810. return false;
  1811. }
  1812. struct stat st;
  1813. if ( stat(file, &st) < 0 )
  1814. {
  1815. return false;
  1816. }
  1817. mode = st.st_mode;
  1818. return true;
  1819. }
  1820. bool SystemTools::SetPermissions(const char* file, mode_t mode)
  1821. {
  1822. if ( !file )
  1823. {
  1824. return false;
  1825. }
  1826. if ( !SystemTools::FileExists(file) )
  1827. {
  1828. return false;
  1829. }
  1830. if ( chmod(file, mode) < 0 )
  1831. {
  1832. return false;
  1833. }
  1834. return true;
  1835. }
  1836. // These must NOT be initialized. Default initialization to zero is
  1837. // necessary.
  1838. unsigned int SystemToolsManagerCount;
  1839. SystemToolsTranslationMap *SystemTools::TranslationMap;
  1840. // SystemToolsManager manages the SystemTools singleton.
  1841. // SystemToolsManager should be included in any translation unit
  1842. // that will use SystemTools or that implements the singleton
  1843. // pattern. It makes sure that the SystemTools singleton is created
  1844. // before and destroyed after all other singletons in CMake.
  1845. SystemToolsManager::SystemToolsManager()
  1846. {
  1847. if(++SystemToolsManagerCount == 1)
  1848. {
  1849. SystemTools::ClassInitialize();
  1850. }
  1851. }
  1852. SystemToolsManager::~SystemToolsManager()
  1853. {
  1854. if(--SystemToolsManagerCount == 0)
  1855. {
  1856. SystemTools::ClassFinalize();
  1857. }
  1858. }
  1859. void SystemTools::ClassInitialize()
  1860. {
  1861. SystemTools::TranslationMap = new SystemToolsTranslationMap;
  1862. }
  1863. void SystemTools::ClassFinalize()
  1864. {
  1865. delete SystemTools::TranslationMap;
  1866. }
  1867. } // namespace KWSYS_NAMESPACE
  1868. #if defined(_MSC_VER) && defined(_DEBUG)
  1869. # include <crtdbg.h>
  1870. # include <stdio.h>
  1871. # include <stdlib.h>
  1872. namespace KWSYS_NAMESPACE
  1873. {
  1874. static int SystemToolsDebugReport(int, char* message, int*)
  1875. {
  1876. fprintf(stderr, message);
  1877. exit(1);
  1878. }
  1879. void SystemTools::EnableMSVCDebugHook()
  1880. {
  1881. if(getenv("DART_TEST_FROM_DART"))
  1882. {
  1883. _CrtSetReportHook(SystemToolsDebugReport);
  1884. }
  1885. }
  1886. } // namespace KWSYS_NAMESPACE
  1887. #else
  1888. namespace KWSYS_NAMESPACE
  1889. {
  1890. void SystemTools::EnableMSVCDebugHook() {}
  1891. } // namespace KWSYS_NAMESPACE
  1892. #endif