SystemTools.cxx 132 KB
Newer Older
1
2
3
/*============================================================================
  KWSys - Kitware System Library
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8
9
10
11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
13
14
15
16
17
18

#ifdef __osf__
#  define _OSF_SOURCE
#  define _POSIX_C_SOURCE 199506L
#  define _XOPEN_SOURCE_EXTENDED
#endif

19
20
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) || defined(__MINGW32__))
#  define KWSYS_WINDOWS_DIRS
21
22
23
24
#else
#  if defined(__SUNPRO_CC)
#    include <fcntl.h>
#  endif
25
26
#endif

27
#include "kwsysPrivate.h"
28
#include KWSYS_HEADER(RegularExpression.hxx)
29
#include KWSYS_HEADER(SystemTools.hxx)
30
#include KWSYS_HEADER(Directory.hxx)
31
32
#include KWSYS_HEADER(FStream.hxx)
#include KWSYS_HEADER(Encoding.hxx)
33

34
35
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(ios/fstream)
36
#include KWSYS_HEADER(ios/sstream)
37

38
39
#include KWSYS_HEADER(stl/set)

40
41
42
43
44
// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "SystemTools.hxx.in"
# include "Directory.hxx.in"
45
46
# include "FStream.hxx.in"
# include "Encoding.hxx.in"
47
48
49
50
51
# include "kwsys_ios_iostream.h.in"
# include "kwsys_ios_fstream.h.in"
# include "kwsys_ios_sstream.h.in"
#endif

52
53
54
55
#ifdef _MSC_VER
# pragma warning (disable: 4786)
#endif

56
57
58
#if defined(__sgi) && !defined(__GNUC__)
# pragma set woff 1375 /* base class destructor not virtual */
#endif
59

60
61
#include <ctype.h>
#include <errno.h>
62
63
#ifdef __QNX__
# include <malloc.h> /* for malloc/free on QNX */
64
#endif
65
66
67
68
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
69
70
71
72
#include <time.h>

// support for realpath call
#ifndef _WIN32
73
#include <sys/time.h>
74
#include <utime.h>
75
76
#include <limits.h>
#include <sys/wait.h>
77
78
#include <sys/ioctl.h>
#include <unistd.h>
79
#include <pwd.h>
80
81
#ifndef __VMS
#include <sys/param.h>
Andy Cedilnik's avatar
Andy Cedilnik committed
82
#include <termios.h>
83
#endif
84
#include <signal.h>    /* sigprocmask */
85
86
#endif

87
88
// Windows API.
#if defined(_WIN32)
89
# include <windows.h>
90
91
92
# ifndef INVALID_FILE_ATTRIBUTES
#  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
93
94
95
# if defined(_MSC_VER) && _MSC_VER >= 1800
#  define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# endif
96
97
98
#elif defined (__CYGWIN__)
# include <windows.h>
# undef _WIN32
99
100
#endif

101
102
103
104
#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
extern char **environ;
#endif

105
#ifdef __CYGWIN__
106
# include <sys/cygwin.h>
107
108
#endif

Alexander Neundorf's avatar
   
Alexander Neundorf committed
109
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
Alexander Neundorf's avatar
   
Alexander Neundorf committed
110
// same for TIOCGWINSZ
Alexander Neundorf's avatar
   
Alexander Neundorf committed
111
112
#if defined(_WIN32) || defined (__LIBCATAMOUNT__)
# undef HAVE_GETPWNAM
Alexander Neundorf's avatar
   
Alexander Neundorf committed
113
# undef HAVE_TTY_INFO
Alexander Neundorf's avatar
   
Alexander Neundorf committed
114
115
#else
# define HAVE_GETPWNAM 1
Alexander Neundorf's avatar
   
Alexander Neundorf committed
116
# define HAVE_TTY_INFO 1
Alexander Neundorf's avatar
   
Alexander Neundorf committed
117
118
#endif

119
#define VTK_URL_PROTOCOL_REGEX "([a-zA-Z0-9]*)://(.*)"
120
#define VTK_URL_REGEX "([a-zA-Z0-9]*)://(([A-Za-z0-9]+)(:([^:@]+))?@)?([^:@/]+)(:([0-9]+))?/(.+)?"
121

122
123
124
125
126
#ifdef _MSC_VER
#include <sys/utime.h>
#else
#include <utime.h>
#endif
Alexander Neundorf's avatar
   
Alexander Neundorf committed
127

128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// This is a hack to prevent warnings about these functions being
// declared but not referenced.
#if defined(__sgi) && !defined(__GNUC__)
# include <sys/termios.h>
namespace KWSYS_NAMESPACE
{
class SystemToolsHack
{
public:
  enum
  {
    Ref1 = sizeof(cfgetospeed(0)),
    Ref2 = sizeof(cfgetispeed(0)),
    Ref3 = sizeof(tcgetattr(0, 0)),
    Ref4 = sizeof(tcsetattr(0, 0, 0)),
    Ref5 = sizeof(cfsetospeed(0,0)),
    Ref6 = sizeof(cfsetispeed(0,0))
  };
};
}
#endif
150

151
#if defined(_WIN32) && (defined(_MSC_VER) || defined(__WATCOMC__) ||defined(__BORLANDC__) || defined(__MINGW32__))
152
#include <io.h>
153
154
#include <direct.h>
#define _unlink unlink
155
#endif
156
157
158
159
160
161
162
163
164

/* The maximum length of a file name.  */
#if defined(PATH_MAX)
# define KWSYS_SYSTEMTOOLS_MAXPATH PATH_MAX
#elif defined(MAXPATHLEN)
# define KWSYS_SYSTEMTOOLS_MAXPATH MAXPATHLEN
#else
# define KWSYS_SYSTEMTOOLS_MAXPATH 16384
#endif
165
166
167
168
169
170
171
#if defined(__WATCOMC__)
#include <direct.h>
#define _mkdir mkdir
#define _rmdir rmdir
#define _getcwd getcwd
#define _chdir chdir
#endif
172

173
#if defined(__BEOS__) && !defined(__ZETA__)
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <be/kernel/OS.h>
#include <be/storage/Path.h>

// BeOS 5 doesn't have usleep(), but it has snooze(), which is identical.
static inline void usleep(unsigned int msec)
{
  ::snooze(msec);
}

// BeOS 5 also doesn't have realpath(), but its C++ API offers something close.
static inline char *realpath(const char *path, char *resolved_path)
{
  const size_t maxlen = KWSYS_SYSTEMTOOLS_MAXPATH;
  snprintf(resolved_path, maxlen, "%s", path);
  BPath normalized(resolved_path, NULL, true);
  const char *resolved = normalized.Path();
190
  if (resolved != NULL)   // NULL == No such file.
191
    {
192
    if (snprintf(resolved_path, maxlen, "%s", resolved) < maxlen)
193
194
195
196
197
198
199
200
      {
      return resolved_path;
      }
    }
  return NULL;   // something went wrong.
}
#endif

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#ifdef _WIN32
static time_t windows_filetime_to_posix_time(const FILETIME& ft)
{
  LARGE_INTEGER date;
  date.HighPart = ft.dwHighDateTime;
  date.LowPart = ft.dwLowDateTime;

  // removes the diff between 1970 and 1601
  date.QuadPart -= ((LONGLONG)(369 * 365 + 89) * 24 * 3600 * 10000000);

  // converts back from 100-nanoseconds to seconds
  return date.QuadPart / 10000000;
}
#endif

216
#ifdef KWSYS_WINDOWS_DIRS
217
218
#include <wctype.h>

219
inline int Mkdir(const kwsys_stl::string& dir)
220
{
221
222
  return _wmkdir(
    KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str());
223
}
224
inline int Rmdir(const kwsys_stl::string& dir)
225
{
226
227
  return _wrmdir(
    KWSYS_NAMESPACE::SystemTools::ConvertToWindowsExtendedPath(dir).c_str());
228
}
229
230
inline const char* Getcwd(char* buf, unsigned int len)
{
231
  std::vector<wchar_t> w_buf(len);
232
  if(_wgetcwd(&w_buf[0], len))
233
    {
234
    // make sure the drive letter is capital
235
    if(wcslen(&w_buf[0]) > 1 && w_buf[1] == L':')
236
      {
237
      w_buf[0] = towupper(w_buf[0]);
238
      }
239
240
241
    std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
    strcpy(buf, tmp.c_str());
    return buf;
242
    }
243
  return 0;
244
}
245
inline int Chdir(const kwsys_stl::string& dir)
246
247
{
  #if defined(__BORLANDC__)
248
  return chdir(dir.c_str());
249
  #else
250
  return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
251
252
  #endif
}
253
inline void Realpath(const kwsys_stl::string& path, kwsys_stl::string & resolved_path)
254
{
255
256
257
258
259
  kwsys_stl::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
  wchar_t *ptemp;
  wchar_t fullpath[MAX_PATH];
  if( GetFullPathNameW(tmp.c_str(), sizeof(fullpath)/sizeof(fullpath[0]),
                       fullpath, &ptemp) )
260
    {
261
    resolved_path = KWSYS_NAMESPACE::Encoding::ToNarrow(fullpath);
262
    KWSYS_NAMESPACE::SystemTools::ConvertToUnixSlashes(resolved_path);
263
    }
264
265
266
267
  else
    {
    resolved_path = path;
    }
268
}
269
270
271
272
#else
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
273
inline int Mkdir(const kwsys_stl::string& dir)
274
{
275
  return mkdir(dir.c_str(), 00777);
276
}
277
inline int Rmdir(const kwsys_stl::string& dir)
278
{
279
  return rmdir(dir.c_str());
280
}
281
282
inline const char* Getcwd(char* buf, unsigned int len)
{
283
  return getcwd(buf, len);
284
}
285

286
inline int Chdir(const kwsys_stl::string& dir)
287
{
288
  return chdir(dir.c_str());
289
}
290
inline void Realpath(const kwsys_stl::string& path, kwsys_stl::string & resolved_path)
291
{
292
  char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
293

294
  char *ret = realpath(path.c_str(), resolved_name);
295
296
297
298
299
300
301
302
303
  if(ret)
    {
    resolved_path = ret;
    }
  else
    {
    // if path resolution fails, return what was passed in
    resolved_path = path;
    }
304
}
305
306
#endif

307
308
309
310
311
312
313
314
315
316
317
318
#if !defined(_WIN32) && defined(__COMO__)
// Hack for como strict mode to avoid defining _SVID_SOURCE or _BSD_SOURCE.
extern "C"
{
extern FILE *popen (__const char *__command, __const char *__modes) __THROW;
extern int pclose (FILE *__stream) __THROW;
extern char *realpath (__const char *__restrict __name,
                       char *__restrict __resolved) __THROW;
extern char *strdup (__const char *__s) __THROW;
extern int putenv (char *__string) __THROW;
}
#endif
319
320
321
322

namespace KWSYS_NAMESPACE
{

323
324
325
326
327
328
329
330
331
332
333
double SystemTools::GetTime(void)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
  FILETIME ft;
  GetSystemTimeAsFileTime(&ft);
  return (429.4967296*ft.dwHighDateTime
          + 0.0000001*ft.dwLowDateTime
          - 11644473600.0);
#else
  struct timeval t;
  gettimeofday(&t, 0);
334
  return 1.0*double(t.tv_sec) + 0.000001*double(t.tv_usec);
335
336
337
#endif
}

338
class SystemToolsTranslationMap :
339
340
341
342
    public kwsys_stl::map<kwsys_stl::string,kwsys_stl::string>
{
};

343
// adds the elements of the env variable path to the arg passed in
344
void SystemTools::GetPath(kwsys_stl::vector<kwsys_stl::string>& path, const char* env)
345
346
{
#if defined(_WIN32) && !defined(__CYGWIN__)
347
  const char pathSep = ';';
348
#else
349
  const char pathSep = ':';
350
#endif
351
352
353
354
  if(!env)
    {
    env = "PATH";
    }
355
356
357
358
359
360
361
  const char* cpathEnv = SystemTools::GetEnv(env);
  if ( !cpathEnv )
    {
    return;
    }

  kwsys_stl::string pathEnv = cpathEnv;
362
363

  // A hack to make the below algorithm work.
364
  if(!pathEnv.empty() && *pathEnv.rbegin() != pathSep)
365
366
367
    {
    pathEnv += pathSep;
    }
368
  kwsys_stl::string::size_type start =0;
369
370
371
  bool done = false;
  while(!done)
    {
372
373
    kwsys_stl::string::size_type endpos = pathEnv.find(pathSep, start);
    if(endpos != kwsys_stl::string::npos)
374
      {
375
      path.push_back(pathEnv.substr(start, endpos-start));
376
377
378
379
380
381
382
      start = endpos+1;
      }
    else
      {
      done = true;
      }
    }
383
  for(kwsys_stl::vector<kwsys_stl::string>::iterator i = path.begin();
384
385
386
387
388
389
      i != path.end(); ++i)
    {
    SystemTools::ConvertToUnixSlashes(*i);
    }
}

Brad King's avatar
Brad King committed
390
391
392
393
394
const char* SystemTools::GetEnv(const char* key)
{
  return getenv(key);
}

395
396
397
398
399
const char* SystemTools::GetEnv(const kwsys_stl::string& key)
{
  return SystemTools::GetEnv(key.c_str());
}

400
bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
Brad King's avatar
Brad King committed
401
402
403
404
405
406
407
408
409
410
411
412
{
  const char* v = getenv(key);
  if(v)
    {
    result = v;
    return true;
    }
  else
    {
    return false;
    }
}
413

414
415
416
417
418
bool SystemTools::GetEnv(const kwsys_stl::string& key, kwsys_stl::string& result)
{
  return SystemTools::GetEnv(key.c_str(), result);
}

419
420
421
422
423
424
//----------------------------------------------------------------------------

#if defined(__CYGWIN__) || defined(__GLIBC__)
# define KWSYS_PUTENV_NAME  /* putenv("A")  removes A.  */
#elif defined(_WIN32)
# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
425
426
#endif

427
428
429
#if KWSYS_CXX_HAS_UNSETENV
/* unsetenv("A") removes A from the environment.
   On older platforms it returns void instead of int.  */
430
static int kwsysUnPutEnv(const kwsys_stl::string& env)
Bill Hoffman's avatar
Bill Hoffman committed
431
{
432
433
  size_t pos = env.find('=');
  if(pos != env.npos)
434
    {
435
    std::string name = env.substr(0, pos);
436
437
438
439
    unsetenv(name.c_str());
    }
  else
    {
440
    unsetenv(env.c_str());
441
442
443
    }
  return 0;
}
Bill Hoffman's avatar
Bill Hoffman committed
444

445
446
#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
/* putenv("A=") or putenv("A") removes A from the environment.  */
447
static int kwsysUnPutEnv(const kwsys_stl::string& env)
Bill Hoffman's avatar
Bill Hoffman committed
448
{
449
  int err = 0;
450
451
  size_t pos = env.find('=');
  size_t const len = pos == env.npos ? env.size() : pos;
452
453
454
455
456
457
458
459
460
461
462
# ifdef KWSYS_PUTENV_EMPTY
  size_t const sz = len + 2;
# else
  size_t const sz = len + 1;
# endif
  char local_buf[256];
  char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
  if(!buf)
    {
    return -1;
    }
463
  strncpy(buf, env.c_str(), len);
464
465
466
467
# ifdef KWSYS_PUTENV_EMPTY
  buf[len] = '=';
  buf[len+1] = 0;
  if(putenv(buf) < 0)
Bill Hoffman's avatar
Bill Hoffman committed
468
    {
469
    err = errno;
Bill Hoffman's avatar
Bill Hoffman committed
470
    }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
# else
  buf[len] = 0;
  if(putenv(buf) < 0 && errno != EINVAL)
    {
    err = errno;
    }
# endif
  if(buf != local_buf)
    {
    free(buf);
    }
  if(err)
    {
    errno = err;
    return -1;
    }
  return 0;
}

#else
/* Manipulate the "environ" global directly.  */
492
static int kwsysUnPutEnv(const kwsys_stl::string& env)
493
{
494
495
  size_t pos = env.find('=');
  size_t const len = pos == env.npos ? env.size() : pos;
496
497
498
499
500
501
  int in = 0;
  int out = 0;
  while(environ[in])
    {
    if(strlen(environ[in]) > len &&
       environ[in][len] == '=' &&
502
       strncmp(env.c_str(), environ[in], len) == 0)
503
504
505
506
507
508
509
510
511
512
513
514
515
516
      {
      ++in;
      }
    else
      {
      environ[out++] = environ[in++];
      }
    }
  while(out < in)
    {
    environ[out++] = 0;
    }
  return 0;
}
517
#endif
518
519
520
521
522
523
524

//----------------------------------------------------------------------------

#if KWSYS_CXX_HAS_SETENV

/* setenv("A", "B", 1) will set A=B in the environment and makes its
   own copies of the strings.  */
525
bool SystemTools::PutEnv(const kwsys_stl::string& env)
526
{
527
528
  size_t pos = env.find('=');
  if(pos != env.npos)
529
    {
530
531
    std::string name = env.substr(0, pos);
    return setenv(name.c_str(), env.c_str() + pos + 1, 1) == 0;
532
533
534
535
536
    }
  else
    {
    return kwsysUnPutEnv(env) == 0;
    }
Bill Hoffman's avatar
Bill Hoffman committed
537
}
538

539
bool SystemTools::UnPutEnv(const kwsys_stl::string& env)
540
{
541
  return kwsysUnPutEnv(env) == 0;
Bill Hoffman's avatar
Bill Hoffman committed
542
543
}

544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
#else

/* putenv("A=B") will set A=B in the environment.  Most putenv implementations
   put their argument directly in the environment.  They never free the memory
   on program exit.  Keep an active set of pointers to memory we allocate and
   pass to putenv, one per environment key.  At program exit remove any
   environment values that may still reference memory we allocated.  Then free
   the memory.  This will not affect any environment values we never set.  */

# ifdef __INTEL_COMPILER
#  pragma warning disable 444 /* base has non-virtual destructor */
# endif

/* Order by environment key only (VAR from VAR=VALUE).  */
struct kwsysEnvCompare
{
  bool operator() (const char* l, const char* r) const
    {
    const char* leq = strchr(l, '=');
    const char* req = strchr(r, '=');
    size_t llen = leq? (leq-l) : strlen(l);
    size_t rlen = req? (req-r) : strlen(r);
    if(llen == rlen)
      {
      return strncmp(l,r,llen) < 0;
      }
    else
      {
      return strcmp(l,r) < 0;
      }
    }
};

class kwsysEnv: public kwsys_stl::set<const char*, kwsysEnvCompare>
{
  class Free
  {
    const char* Env;
  public:
    Free(const char* env): Env(env) {}
    ~Free() { free(const_cast<char*>(this->Env)); }
  };
public:
  typedef kwsys_stl::set<const char*, kwsysEnvCompare> derived;
  ~kwsysEnv()
    {
    for(derived::iterator i = this->begin(); i != this->end(); ++i)
      {
      kwsysUnPutEnv(*i);
      free(const_cast<char*>(*i));
      }
    }
  const char* Release(const char* env)
    {
    const char* old = 0;
    derived::iterator i = this->find(env);
    if(i != this->end())
      {
      old = *i;
      this->erase(i);
      }
    return old;
    }
  bool Put(const char* env)
    {
    Free oldEnv(this->Release(env));
    static_cast<void>(oldEnv);
    char* newEnv = strdup(env);
    this->insert(newEnv);
    return putenv(newEnv) == 0;
    }
  bool UnPut(const char* env)
    {
    Free oldEnv(this->Release(env));
    static_cast<void>(oldEnv);
    return kwsysUnPutEnv(env) == 0;
    }
};

static kwsysEnv kwsysEnvInstance;

625
bool SystemTools::PutEnv(const kwsys_stl::string& env)
626
{
627
  return kwsysEnvInstance.Put(env.c_str());
628
629
}

630
bool SystemTools::UnPutEnv(const kwsys_stl::string& env)
631
{
632
  return kwsysEnvInstance.UnPut(env.c_str());
633
634
635
636
637
638
}

#endif

//----------------------------------------------------------------------------

639
640
const char* SystemTools::GetExecutableExtension()
{
Bill Hoffman's avatar
Bill Hoffman committed
641
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
642
643
644
  return ".exe";
#else
  return "";
645
#endif
646
647
}

648
FILE* SystemTools::Fopen(const kwsys_stl::string& file, const char* mode)
649
650
{
#ifdef _WIN32
651
  return _wfopen(SystemTools::ConvertToWindowsExtendedPath(file).c_str(),
652
653
                 Encoding::ToWide(mode).c_str());
#else
654
  return fopen(file.c_str(), mode);
655
656
#endif
}
657
658
659

bool SystemTools::MakeDirectory(const char* path)
{
Bill Hoffman's avatar
Bill Hoffman committed
660
661
662
663
  if(!path)
    {
    return false;
    }
664
665
666
667
668
  return SystemTools::MakeDirectory(kwsys_stl::string(path));
}

bool SystemTools::MakeDirectory(const kwsys_stl::string& path)
{
669
670
  if(SystemTools::FileExists(path))
    {
671
    return SystemTools::FileIsDirectory(path);
672
    }
673
  if(path.empty())
674
675
676
    {
    return false;
    }
677
  kwsys_stl::string dir = path;
678
679
  SystemTools::ConvertToUnixSlashes(dir);

680
  kwsys_stl::string::size_type pos = 0;
681
682
  kwsys_stl::string topdir;
  while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
683
684
    {
    topdir = dir.substr(0, pos);
685
    Mkdir(topdir);
686
687
    pos++;
    }
688
  topdir = dir;
689
  if(Mkdir(topdir) != 0)
690
691
692
693
694
    {
    // There is a bug in the Borland Run time library which makes MKDIR
    // return EACCES when it should return EEXISTS
    // if it is some other error besides directory exists
    // then return false
695
    if( (errno != EEXIST)
696
#ifdef __BORLANDC__
697
698
        && (errno != EACCES)
#endif
699
700
701
702
703
704
705
706
707
708
709
      )
      {
      return false;
      }
    }
  return true;
}


// replace replace with with as many times as it shows up in source.
// write the result into source.
710
void SystemTools::ReplaceString(kwsys_stl::string& source,
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
                                const kwsys_stl::string& replace,
                                const kwsys_stl::string& with)
{
  // do while hangs if replaceSize is 0
  if (replace.empty())
    {
    return;
    }

  SystemTools::ReplaceString(source, replace.c_str(), replace.size(), with);
}

void SystemTools::ReplaceString(kwsys_stl::string& source,
                                const char* replace,
                                const char* with)
{
  // do while hangs if replaceSize is 0
  if (!*replace)
    {
    return;
    }

  SystemTools::ReplaceString(source, replace, strlen(replace), with ? with : "");
}

void SystemTools::ReplaceString(kwsys_stl::string& source,
                                const char* replace,
                                size_t replaceSize,
                                const kwsys_stl::string& with)
740
{
Ken Martin's avatar
Ken Martin committed
741
  const char *src = source.c_str();
Bill Lorensen's avatar
Bill Lorensen committed
742
  char *searchPos = const_cast<char *>(strstr(src,replace));
743

744
  // get out quick if string is not found
Ken Martin's avatar
Ken Martin committed
745
  if (!searchPos)
746
747
748
    {
    return;
    }
Ken Martin's avatar
Ken Martin committed
749
750
751
752
753

  // perform replacements until done
  char *orig = strdup(src);
  char *currentPos = orig;
  searchPos = searchPos - src + orig;
754

Ken Martin's avatar
Ken Martin committed
755
  // initialize the result
Ken Martin's avatar
Ken Martin committed
756
  source.erase(source.begin(),source.end());
Ken Martin's avatar
Ken Martin committed
757
  do
758
    {
Ken Martin's avatar
Ken Martin committed
759
760
761
762
    *searchPos = '\0';
    source += currentPos;
    currentPos = searchPos + replaceSize;
    // replace
763
    source += with;
Ken Martin's avatar
Ken Martin committed
764
    searchPos = strstr(currentPos,replace);
765
    }
Ken Martin's avatar
Ken Martin committed
766
767
768
769
770
  while (searchPos);

  // copy any trailing text
  source += currentPos;
  free(orig);
771
772
}

773
774
775
776
777
778
779
780
781
#if defined(KEY_WOW64_32KEY) && defined(KEY_WOW64_64KEY)
# define KWSYS_ST_KEY_WOW64_32KEY KEY_WOW64_32KEY
# define KWSYS_ST_KEY_WOW64_64KEY KEY_WOW64_64KEY
#else
# define KWSYS_ST_KEY_WOW64_32KEY 0x0200
# define KWSYS_ST_KEY_WOW64_64KEY 0x0100
#endif

#if defined(_WIN32) && !defined(__CYGWIN__)
782
static bool SystemToolsParseRegistryKey(const kwsys_stl::string& key,
783
784
785
786
787
788
                                        HKEY& primaryKey,
                                        kwsys_stl::string& second,
                                        kwsys_stl::string& valuename)
{
  kwsys_stl::string primary = key;

789
  size_t start = primary.find('\\');
790
791
792
793
794
  if (start == kwsys_stl::string::npos)
    {
    return false;
    }

795
  size_t valuenamepos = primary.find(';');
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
  if (valuenamepos != kwsys_stl::string::npos)
    {
    valuename = primary.substr(valuenamepos+1);
    }

  second = primary.substr(start+1, valuenamepos-start-1);
  primary = primary.substr(0, start);

  if (primary == "HKEY_CURRENT_USER")
    {
    primaryKey = HKEY_CURRENT_USER;
    }
  if (primary == "HKEY_CURRENT_CONFIG")
    {
    primaryKey = HKEY_CURRENT_CONFIG;
    }
  if (primary == "HKEY_CLASSES_ROOT")
    {
    primaryKey = HKEY_CLASSES_ROOT;
    }
  if (primary == "HKEY_LOCAL_MACHINE")
    {
    primaryKey = HKEY_LOCAL_MACHINE;
    }
  if (primary == "HKEY_USERS")
    {
    primaryKey = HKEY_USERS;
    }

  return true;
}

828
829
830
static DWORD SystemToolsMakeRegistryMode(DWORD mode,
                                         SystemTools::KeyWOW64 view)
{
831
  // only add the modes when on a system that supports Wow64.
832
  static FARPROC wow64p = GetProcAddress(GetModuleHandleW(L"kernel32"),
833
                                         "IsWow64Process");
834
835
836
837
838
  if(wow64p == NULL)
    {
    return mode;
    }

839
840
841
842
843
844
845
846
847
848
849
850
  if(view == SystemTools::KeyWOW64_32)
    {
    return mode | KWSYS_ST_KEY_WOW64_32KEY;
    }
  else if(view == SystemTools::KeyWOW64_64)
    {
    return mode | KWSYS_ST_KEY_WOW64_64KEY;
    }
  return mode;
}
#endif

851
852
#if defined(_WIN32) && !defined(__CYGWIN__)
bool
853
SystemTools::GetRegistrySubKeys(const kwsys_stl::string& key,
854
855
856
857
858
859
860
861
862
863
864
865
                                kwsys_stl::vector<kwsys_stl::string>& subkeys,
                                KeyWOW64 view)
{
  HKEY primaryKey = HKEY_CURRENT_USER;
  kwsys_stl::string second;
  kwsys_stl::string valuename;
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
    {
    return false;
    }

  HKEY hKey;
866
867
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
868
869
870
871
872
873
874
875
                  0,
                  SystemToolsMakeRegistryMode(KEY_READ, view),
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
876
    wchar_t name[1024];
877
878
879
    DWORD dwNameSize = sizeof(name)/sizeof(name[0]);

    DWORD i = 0;
880
    while (RegEnumKeyW(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
881
      {
882
      subkeys.push_back(Encoding::ToNarrow(name));
883
884
885
886
887
888
889
890
891
      ++i;
      }

    RegCloseKey(hKey);
    }

  return true;
}
#else
892
bool SystemTools::GetRegistrySubKeys(const kwsys_stl::string&,
893
894
895
896
897
898
899
                                     kwsys_stl::vector<kwsys_stl::string>&,
                                     KeyWOW64)
{
  return false;
}
#endif

900
// Read a registry value.
901
// Example :
902
903
904
905
906
907
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will return the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will return the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
908
bool SystemTools::ReadRegistryValue(const kwsys_stl::string& key, kwsys_stl::string &value,
909
                                    KeyWOW64 view)
910
{
911
  bool valueset = false;
912
  HKEY primaryKey = HKEY_CURRENT_USER;
913
914
  kwsys_stl::string second;
  kwsys_stl::string valuename;
915
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
916
917
918
919
920
    {
    return false;
    }

  HKEY hKey;
921
922
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
923
                  0,
924
                  SystemToolsMakeRegistryMode(KEY_READ, view),
925
926
927
928
929
930
931
932
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
    DWORD dwType, dwSize;
    dwSize = 1023;
933
934
935
    wchar_t data[1024];
    if(RegQueryValueExW(hKey,
                       Encoding::ToWide(valuename).c_str(),
936
937
938
                       NULL,
                       &dwType,
                       (BYTE *)data,
939
940
941
942
                       &dwSize) == ERROR_SUCCESS)
      {
      if (dwType == REG_SZ)
        {
943
        value = Encoding::ToNarrow(data);
944
945
946
947
        valueset = true;
        }
      else if (dwType == REG_EXPAND_SZ)
        {
948
        wchar_t expanded[1024];
949
        DWORD dwExpandedSize = sizeof(expanded)/sizeof(expanded[0]);
950
951
        if(ExpandEnvironmentStringsW(data, expanded,
            dwExpandedSize))
952
          {
953
          value = Encoding::ToNarrow(expanded);
954
955
          valueset = true;
          }
956
957
        }
      }
958
959

    RegCloseKey(hKey);
960
    }
961
962

  return valueset;
963
964
}
#else
965
bool SystemTools::ReadRegistryValue(const kwsys_stl::string&, kwsys_stl::string &,
966
                                    KeyWOW64)
967
968
969
970
971
972
973
{
  return false;
}
#endif


// Write a registry value.
974
// Example :
975
976
977
978
979
980
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will set the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will set the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
981
982
bool SystemTools::WriteRegistryValue(const kwsys_stl::string& key,
                                     const kwsys_stl::string& value,
983
                                     KeyWOW64 view)
984
{
985
  HKEY primaryKey = HKEY_CURRENT_USER;
986
987
  kwsys_stl::string second;
  kwsys_stl::string valuename;
988
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
989
990
991
992
993
994
    {
    return false;
    }

  HKEY hKey;
  DWORD dwDummy;
995
996
997
  wchar_t lpClass[] = L"";
  if(RegCreateKeyExW(primaryKey,
                    Encoding::ToWide(second).c_str(),
998
                    0,
999
                    lpClass,
1000
                    REG_OPTION_NON_VOLATILE,
1001
                    SystemToolsMakeRegistryMode(KEY_WRITE, view),
1002
1003
1004
1005
1006
1007
1008
                    NULL,
                    &hKey,
                    &dwDummy) != ERROR_SUCCESS)
    {
    return false;
    }

1009
1010
1011
  std::wstring wvalue = Encoding::ToWide(value);
  if(RegSetValueExW(hKey,
                   Encoding::ToWide(valuename).c_str(),
1012
1013
                   0,
                   REG_SZ,
1014
1015
                   (CONST BYTE *)wvalue.c_str(),
                   (DWORD)(sizeof(wchar_t) * (wvalue.size() + 1))) == ERROR_SUCCESS)
1016
1017
1018
1019
1020
1021
    {
    return true;
    }
  return false;
}
#else
1022
bool SystemTools::WriteRegistryValue(const kwsys_stl::string&, const kwsys_stl::string&, KeyWOW64)
1023
1024
1025
1026
1027
1028
{
  return false;
}
#endif

// Delete a registry value.
1029
// Example :
1030
1031
1032
1033
1034
1035
//      HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
//      =>  will delete the data of the "default" value of the key
//      HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
//      =>  will delete  the data of the "Root" value of the key

#if defined(_WIN32) && !defined(__CYGWIN__)
1036
bool SystemTools::DeleteRegistryValue(const kwsys_stl::string& key, KeyWOW64 view)
1037
{
1038
  HKEY primaryKey = HKEY_CURRENT_USER;
1039
1040
  kwsys_stl::string second;
  kwsys_stl::string valuename;
1041
  if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
1042
1043
1044
1045
1046
    {
    return false;
    }

  HKEY hKey;
1047
1048
  if(RegOpenKeyExW(primaryKey,
                  Encoding::ToWide(second).c_str(),
1049
                  0,
1050
                  SystemToolsMakeRegistryMode(KEY_WRITE, view),
1051
1052
1053
1054
1055
1056
                  &hKey) != ERROR_SUCCESS)
    {
    return false;
    }
  else
    {
1057
    if(RegDeleteValue(hKey,
1058
1059
                      (LPTSTR)valuename.c_str()) == ERROR_SUCCESS)
      {
1060
      RegCloseKey(hKey);
1061
1062
1063
1064
1065
1066
      return true;
      }
    }
  return false;
}
#else
1067
bool SystemTools::DeleteRegistryValue(const kwsys_stl::string&, KeyWOW64)
1068
1069
1070
1071
1072
{
  return false;
}
#endif

1073
bool SystemTools::SameFile(const kwsys_stl::string& file1, const kwsys_stl::string& file2)
1074
1075
1076
1077
{
#ifdef _WIN32
  HANDLE hFile1, hFile2;

1078
  hFile1 = CreateFileW( Encoding::ToWide(file1).c_str(),
1079
                      GENERIC_READ,
1080
1081
1082
1083
1084
1085
                      FILE_SHARE_READ ,
                      NULL,
                      OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS,
                      NULL
    );
1086
  hFile2 = CreateFileW( Encoding::ToWide(file2).c_str(),
1087
1088
                      GENERIC_READ,
                      FILE_SHARE_READ,
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
                      NULL,
                      OPEN_EXISTING,
                      FILE_FLAG_BACKUP_SEMANTICS,
                      NULL
    );
  if( hFile1 == INVALID_HANDLE_VALUE || hFile2 == INVALID_HANDLE_VALUE)
    {
    if(hFile1 != INVALID_HANDLE_VALUE)
      {
      CloseHandle(hFile1);
      }
    if(hFile2 != INVALID_HANDLE_VALUE)
      {
      CloseHandle(hFile2);
      }
    return false;
    }

   BY_HANDLE_FILE_INFORMATION fiBuf1;
   BY_HANDLE_FILE_INFORMATION fiBuf2;
   GetFileInformationByHandle( hFile1, &fiBuf1 );
   GetFileInformationByHandle( hFile2, &fiBuf2 );
   CloseHandle(hFile1);
   CloseHandle(hFile2);
1113
1114
   return (fiBuf1.dwVolumeSerialNumber == fiBuf2.dwVolumeSerialNumber &&
           fiBuf1.nFileIndexHigh == fiBuf2.nFileIndexHigh &&
1115
1116
1117
           fiBuf1.nFileIndexLow == fiBuf2.nFileIndexLow);
#else
  struct stat fileStat1, fileStat2;
1118
  if (stat(file1.c_str(), &fileStat1) == 0 && stat(file2.c_str(), &fileStat2) == 0)
1119
1120
1121
    {
    // see if the files are the same file
    // check the device inode and size
1122
    if(memcmp(&fileStat2.st_dev, &fileStat1.st_dev, sizeof(fileStat1.st_dev)) == 0 &&
1123
       memcmp(&fileStat2.st_ino, &fileStat1.st_ino, sizeof(fileStat1.st_ino)) == 0 &&
1124
1125
       fileStat2.st_size == fileStat1.st_size
      )
1126
1127
1128
1129
1130
1131
1132
1133
      {
      return true;
      }
    }
  return false;
#endif
}

1134
1135
1136
//----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename)
{
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  if(!filename)
    {
    return false;
    }
  return SystemTools::FileExists(kwsys_stl::string(filename));
}

//----------------------------------------------------------------------------
bool SystemTools::FileExists(const kwsys_stl::string& filename)
{
  if(filename.empty())
1148
1149
    {
    return false;
1150
1151
1152
1153
    }
#if defined(__CYGWIN__)
  // Convert filename to native windows path if possible.
  char winpath[MAX_PATH];
1154
  if(SystemTools::PathCygwinToWin32(filename.c_str(), winpath))
1155
    {
1156
    return (GetFileAttributesA(winpath) != INVALID_FILE_ATTRIBUTES);
1157
    }
1158
  return access(filename.c_str(), R_OK) == 0;
1159
#elif defined(_WIN32)
1160
1161
  return (GetFileAttributesW(
            SystemTools::ConvertToWindowsExtendedPath(filename).c_str())
1162
          != INVALID_FILE_ATTRIBUTES);
1163
#else
1164
  return access(filename.c_str(), R_OK) == 0;
1165
#endif
1166
}
1167

1168
1169
1170
1171
//----------------------------------------------------------------------------
bool SystemTools::FileExists(const char* filename, bool isFile)
{
  if(SystemTools::FileExists(filename))
1172
    {
1173
1174
1175
1176
1177
1178
1179
    // If isFile is set return not FileIsDirectory,
    // so this will only be true if it is a file
    return !isFile || !SystemTools::FileIsDirectory(filename);
    }
  return false;
}

1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
//----------------------------------------------------------------------------
bool SystemTools::FileExists(const kwsys_stl::string& filename, bool isFile)
{
  if(SystemTools::FileExists(filename))
    {
    // If isFile is set return not FileIsDirectory,
    // so this will only be true if it is a file
    return !isFile || !SystemTools::FileIsDirectory(filename);
    }
  return false;
}