SystemTools.hxx.in 34.1 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3
4
5
#ifndef @KWSYS_NAMESPACE@_SystemTools_hxx
#define @KWSYS_NAMESPACE@_SystemTools_hxx

6
#include <@KWSYS_NAMESPACE@/Configure.hxx>
7
#include <@KWSYS_NAMESPACE@/Status.hxx>
8
9

#include <iosfwd>
10
#include <map>
Brad King's avatar
Brad King committed
11
12
#include <string>
#include <vector>
13

14
#include <sys/types.h>
15
16
17
// include sys/stat.h after sys/types.h
#include <sys/stat.h>

18
#if !defined(_WIN32) || defined(__CYGWIN__)
19
#  include <unistd.h> // For access permissions for use with access()
20
#endif
21
22

// Required for va_list
23
#include <stdarg.h>
24
25
// Required for FILE*
#include <stdio.h>
Brad King's avatar
Brad King committed
26
#if !defined(va_list)
27
// Some compilers move va_list into the std namespace and there is no way to
28
29
30
31
// tell that this has been done. Playing with things being included before or
// after stdarg.h does not solve things because we do not have control over
// what the user does. This hack solves this problem by moving va_list to our
// own namespace that is local for kwsys.
32
33
34
35
36
namespace std {
} // Required for platforms that do not have std namespace
namespace @KWSYS_NAMESPACE@_VA_LIST {
using namespace std;
typedef va_list hack_va_list;
37
}
38
39
namespace @KWSYS_NAMESPACE@ {
typedef @KWSYS_NAMESPACE@_VA_LIST::hack_va_list va_list;
40
41
}
#endif // va_list
42

43
namespace @KWSYS_NAMESPACE@ {
44

45
class SystemToolsStatic;
46

47
48
49
50
/** \class SystemToolsManager
 * \brief Use to make sure SystemTools is initialized before it is used
 * and is the last static object destroyed
 */
51
52
53
54
55
class @KWSYS_NAMESPACE@_EXPORT SystemToolsManager
{
public:
  SystemToolsManager();
  ~SystemToolsManager();
56
57
58

  SystemToolsManager(const SystemToolsManager&) = delete;
  SystemToolsManager& operator=(const SystemToolsManager&) = delete;
59
60
61
};

// This instance will show up in any translation unit that uses
62
// SystemTools. It will make sure SystemTools is initialized
63
64
// before it is used and is the last static object destroyed.
static SystemToolsManager SystemToolsManagerInstance;
65

66
67
68
69
70
// Flags for use with TestFileAccess.  Use a typedef in case any operating
// system in the future needs a special type.  These are flags that may be
// combined using the | operator.
typedef int TestFilePermissions;
#if defined(_WIN32) && !defined(__CYGWIN__)
71
// On Windows (VC), no system header defines these constants...
72
73
74
75
static const TestFilePermissions TEST_FILE_OK = 0;
static const TestFilePermissions TEST_FILE_READ = 4;
static const TestFilePermissions TEST_FILE_WRITE = 2;
static const TestFilePermissions TEST_FILE_EXECUTE = 1;
76
#else
77
78
79
80
81
// Standard POSIX constants
static const TestFilePermissions TEST_FILE_OK = F_OK;
static const TestFilePermissions TEST_FILE_READ = R_OK;
static const TestFilePermissions TEST_FILE_WRITE = W_OK;
static const TestFilePermissions TEST_FILE_EXECUTE = X_OK;
82
83
#endif

84
85
86
/** \class SystemTools
 * \brief A collection of useful platform-independent system functions.
 */
Brad King's avatar
Brad King committed
87
class @KWSYS_NAMESPACE@_EXPORT SystemTools
88
89
{
public:
90
91
92
93
94
  /** -----------------------------------------------------------------
   *               String Manipulation Routines
   *  -----------------------------------------------------------------
   */

95
96
97
98
99
100
101
  /**
   * Replace symbols in str that are not valid in C identifiers as
   * defined by the 1999 standard, ie. anything except [A-Za-z0-9_].
   * They are replaced with `_' and if the first character is a digit
   * then an underscore is prepended.  Note that this can produce
   * identifiers that the standard reserves (_[A-Z].* and __.*).
   */
Brad King's avatar
Brad King committed
102
  static std::string MakeCidentifier(const std::string& s);
103

Brad King's avatar
Brad King committed
104
  static std::string MakeCindentifier(const std::string& s)
105
106
107
108
  {
    return MakeCidentifier(s);
  }

109
  /**
luz.paz's avatar
luz.paz committed
110
   * Replace replace all occurrences of the string in the source string.
111
   */
112
  static void ReplaceString(std::string& source, const char* replace,
113
                            const char* with);
114
  static void ReplaceString(std::string& source, const std::string& replace,
Brad King's avatar
Brad King committed
115
                            const std::string& with);
116
117
118
119
120

  /**
   * Return a capitalized string (i.e the first letter is uppercased,
   * all other are lowercased).
   */
Brad King's avatar
Brad King committed
121
  static std::string Capitalized(const std::string&);
122

123
  /**
124
125
   * Return a 'capitalized words' string (i.e the first letter of each word
   * is uppercased all other are left untouched though).
126
   */
Brad King's avatar
Brad King committed
127
  static std::string CapitalizedWords(const std::string&);
128

129
  /**
130
131
   * Return a 'uncapitalized words' string (i.e the first letter of each word
   * is lowercased all other are left untouched though).
132
   */
Brad King's avatar
Brad King committed
133
  static std::string UnCapitalizedWords(const std::string&);
134

135
136
137
  /**
   * Return a lower case string
   */
Brad King's avatar
Brad King committed
138
  static std::string LowerCase(const std::string&);
139

140
141
142
  /**
   * Return a lower case string
   */
Brad King's avatar
Brad King committed
143
  static std::string UpperCase(const std::string&);
144

145
146
147
148
  /**
   * Count char in string
   */
  static size_t CountChar(const char* str, char c);
149

150
151
152
153
  /**
   * Remove some characters from a string.
   * Return a pointer to the new resulting string (allocated with 'new')
   */
154
  static char* RemoveChars(const char* str, const char* toremove);
155
156

  /**
157
   * Remove remove all but 0->9, A->F characters from a string.
158
159
160
   * Return a pointer to the new resulting string (allocated with 'new')
   */
  static char* RemoveCharsButUpperHex(const char* str);
161

162
163
164
165
  /**
   * Replace some characters by another character in a string (in-place)
   * Return a pointer to string
   */
166
167
  static char* ReplaceChars(char* str, const char* toreplace,
                            char replacement);
168

169
  /**
170
   * Returns true if str1 starts (respectively ends) with str2
171
172
   */
  static bool StringStartsWith(const char* str1, const char* str2);
Brad King's avatar
Brad King committed
173
  static bool StringStartsWith(const std::string& str1, const char* str2);
174
  static bool StringEndsWith(const char* str1, const char* str2);
Brad King's avatar
Brad King committed
175
  static bool StringEndsWith(const std::string& str1, const char* str2);
176

177
  /**
luz.paz's avatar
luz.paz committed
178
   * Returns a pointer to the last occurrence of str2 in str1
179
180
   */
  static const char* FindLastString(const char* str1, const char* str2);
181

182
183
184
185
186
187
  /**
   * Make a duplicate of the string similar to the strdup C function
   * but use new to create the 'new' string, so one can use
   * 'delete' to remove it. Returns 0 if the input is empty.
   */
  static char* DuplicateString(const char* str);
188

189
190
191
192
  /**
   * Return the string cropped to a given length by removing chars in the
   * center of the string and replacing them with an ellipsis (...)
   */
193
  static std::string CropString(const std::string&, size_t max_len);
194

195
196
197
198
  /** split a path by separator into an array of strings, default is /.
      If isPath is true then the string is treated like a path and if
      s starts with a / then the first element of the returned array will
      be /, so /foo/bar will be [/, foo, bar]
199
  */
200
201
202
  static std::vector<std::string> SplitString(const std::string& s,
                                              char separator = '/',
                                              bool isPath = false);
203
  /**
204
   * Perform a case-independent string comparison
205
   */
206
  static int Strucmp(const char* s1, const char* s2);
207

208
209
210
211
  /**
   * Split a string on its newlines into multiple lines
   * Return false only if the last line stored had no newline
   */
Brad King's avatar
Brad King committed
212
  static bool Split(const std::string& s, std::vector<std::string>& l);
213
214
  static bool Split(const std::string& s, std::vector<std::string>& l,
                    char separator);
215
216

  /**
217
   * Return string with space added between capitalized words
218
   * (i.e. EatMyShorts becomes Eat My Shorts )
219
   * (note that IEatShorts becomes IEat Shorts)
220
   */
221
  static std::string AddSpaceBetweenCapitalizedWords(const std::string&);
222

223
  /**
224
   * Append two or more strings and produce new one.
225
226
   * Programmer must 'delete []' the resulting string, which was allocated
   * with 'new'.
227
228
   * Return 0 if inputs are empty or there was an error
   */
229
230
231
  static char* AppendStrings(const char* str1, const char* str2);
  static char* AppendStrings(const char* str1, const char* str2,
                             const char* str3);
232

233
  /**
234
235
236
237
238
239
240
241
   * Estimate the length of the string that will be produced
   * from printing the given format string and arguments.  The
   * returned length will always be at least as large as the string
   * that will result from printing.
   * WARNING: since va_arg is called to iterate of the argument list,
   * you will not be able to use this 'ap' anymore from the beginning.
   * It's up to you to call va_end though.
   */
242
  static int EstimateFormatLength(const char* format, va_list ap);
243

244
245
246
  /**
   * Escape specific characters in 'str'.
   */
247
248
  static std::string EscapeChars(const char* str, const char* chars_to_escape,
                                 char escape_char = '\\');
249

250
251
252
253
254
  /** -----------------------------------------------------------------
   *               Filename Manipulation Routines
   *  -----------------------------------------------------------------
   */

255
256
257
  /**
   * Replace Windows file system slashes with Unix-style slashes.
   */
Brad King's avatar
Brad King committed
258
  static void ConvertToUnixSlashes(std::string& path);
259
260

#ifdef _WIN32
261
  /** Calls Encoding::ToWindowsExtendedPath.  */
Brad King's avatar
Brad King committed
262
  static std::wstring ConvertToWindowsExtendedPath(const std::string&);
263
264
#endif

265
  /**
266
   * For windows this calls ConvertToWindowsOutputPath and for unix
267
268
   * it calls ConvertToUnixOutputPath
   */
Brad King's avatar
Brad King committed
269
  static std::string ConvertToOutputPath(const std::string&);
270

Ken Martin's avatar
Ken Martin committed
271
272
273
274
  /**
   * Convert the path to a string that can be used in a unix makefile.
   * double slashes are removed, and spaces are escaped.
   */
Brad King's avatar
Brad King committed
275
  static std::string ConvertToUnixOutputPath(const std::string&);
Ken Martin's avatar
Ken Martin committed
276
277
278
279
280
281
282

  /**
   * Convert the path to string that can be used in a windows project or
   * makefile.   Double slashes are removed if they are not at the start of
   * the string, the slashes are converted to windows style backslashes, and
   * if there are spaces in the string it is double quoted.
   */
Brad King's avatar
Brad King committed
283
  static std::string ConvertToWindowsOutputPath(const std::string&);
Ken Martin's avatar
Ken Martin committed
284

285
286
287
288
289
  /**
   * Return true if a path with the given name exists in the current directory.
   */
  static bool PathExists(const std::string& path);

290
  /**
291
   * Return true if a file exists in the current directory.
292
   * If isFile = true, then make sure the file is a file and
293
   * not a directory.  If isFile = false, then return true
294
295
296
   * if it is a file or a directory.  Note that the file will
   * also be checked for read access.  (Currently, this check
   * for read access is only done on POSIX systems.)
297
   */
298
  static bool FileExists(const char* filename, bool isFile);
Brad King's avatar
Brad King committed
299
  static bool FileExists(const std::string& filename, bool isFile);
300
  static bool FileExists(const char* filename);
Brad King's avatar
Brad King committed
301
  static bool FileExists(const std::string& filename);
302

303
304
305
306
307
308
309
310
311
312
313
314
  /**
   * Test if a file exists and can be accessed with the requested
   * permissions.  Symbolic links are followed.  Returns true if
   * the access test was successful.
   *
   * On POSIX systems (including Cygwin), this maps to the access
   * function.  On Windows systems, all existing files are
   * considered readable, and writable files are considered to
   * have the read-only file attribute cleared.
   */
  static bool TestFileAccess(const char* filename,
                             TestFilePermissions permissions);
Brad King's avatar
Brad King committed
315
  static bool TestFileAccess(const std::string& filename,
316
                             TestFilePermissions permissions);
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/**
 * Cross platform wrapper for stat struct
 */
#if defined(_WIN32) && !defined(__CYGWIN__)
  typedef struct _stat64 Stat_t;
#else
  typedef struct stat Stat_t;
#endif

  /**
   * Cross platform wrapper for stat system call
   *
   * On Windows this may not work for paths longer than 250 characters
   * due to limitations of the underlying '_wstat64' call.
   */
  static int Stat(const char* path, Stat_t* buf);
  static int Stat(const std::string& path, Stat_t* buf);
334

335
336
337
  /**
   * Return file length
   */
Brad King's avatar
Brad King committed
338
  static unsigned long FileLength(const std::string& filename);
339

340
341
342
  /**
     Change the modification time or create a file
  */
343
  static Status Touch(std::string const& filename, bool create);
344

345
  /**
346
347
348
   *  Compare file modification times.
   *  Return true for successful comparison and false for error.
   *  When true is returned, result has -1, 0, +1 for
349
   *  f1 older, same, or newer than f2.
350
   */
351
352
  static Status FileTimeCompare(std::string const& f1, std::string const& f2,
                                int* result);
Brad King's avatar
Brad King committed
353

354
355
356
357
358
359
  /**
   *  Get the file extension (including ".") needed for an executable
   *  on the current platform ("" for unix, ".exe" for Windows).
   */
  static const char* GetExecutableExtension();

360
  /**
361
362
363
364
365
   * Given a path on a Windows machine, return the actual case of
   * the path as it exists on disk.  Path components that do not
   * exist on disk are returned unchanged.  Relative paths are always
   * returned unchanged.  Drive letters are always made upper case.
   * This does nothing on non-Windows systems but return the path.
366
   */
Brad King's avatar
Brad King committed
367
  static std::string GetActualCaseForPath(const std::string& path);
368

369
370
371
372
373
  /**
   * Given the path to a program executable, get the directory part of
   * the path with the file stripped off.  If there is no directory
   * part, the empty string is returned.
   */
Brad King's avatar
Brad King committed
374
  static std::string GetProgramPath(const std::string&);
375
376
  static bool SplitProgramPath(const std::string& in_name, std::string& dir,
                               std::string& file, bool errorReport = true);
377
378

  /**
379
380
381
382
383
384
   *  Given argv[0] for a unix program find the full path to a running
   *  executable.  argv0 can be null for windows WinMain programs
   *  in this case GetModuleFileName will be used to find the path
   *  to the running executable.  If argv0 is not a full path,
   *  then this will try to find the full path.  If the path is not
   *  found false is returned, if found true is returned.  An error
385
   *  message of the attempted paths is stored in errorMsg.
386
387
388
389
   *  exeName is the name of the executable.
   *  buildDir is a possibly null path to the build directory.
   *  installPrefix is a possibly null pointer to the install directory.
   */
390
  static bool FindProgramPath(const char* argv0, std::string& pathOut,
391
392
393
394
                              std::string& errorMsg,
                              const char* exeName = nullptr,
                              const char* buildDir = nullptr,
                              const char* installPrefix = nullptr);
395

396
397
398
399
400
401
  /**
   * Given a path to a file or directory, convert it to a full path.
   * This collapses away relative paths relative to the cwd argument
   * (which defaults to the current working directory).  The full path
   * is returned.
   */
402
403
  static std::string CollapseFullPath(std::string const& in_path);
  static std::string CollapseFullPath(std::string const& in_path,
404
                                      const char* in_base);
405
406
  static std::string CollapseFullPath(std::string const& in_path,
                                      std::string const& in_base);
407

408
  /**
409
410
   * Get the real path for a given path, removing all symlinks.  In
   * the event of an error (non-existent path, permissions issue,
411
   * etc.) the original path is returned if errorMessage pointer is
412
   * nullptr.  Otherwise empty string is returned and errorMessage
413
   * contains error description.
414
   */
Brad King's avatar
Brad King committed
415
  static std::string GetRealPath(const std::string& path,
416
                                 std::string* errorMessage = nullptr);
417

418
  /**
419
420
421
   * Split a path name into its root component and the rest of the
   * path.  The root component is one of the following:
   *    "/"   = UNIX full path
422
423
424
   *    "c:/" = Windows full path (can be any drive letter)
   *    "c:"  = Windows drive-letter relative path (can be any drive letter)
   *    "//"  = Network path
425
426
   *    "~/"  = Home path for current user
   *    "~u/" = Home path for user 'u'
427
   *    ""    = Relative path
428
429
430
431
432
   *
   * A pointer to the rest of the path after the root component is
   * returned.  The root component is stored in the "root" string if
   * given.
   */
433
  static const char* SplitPathRootComponent(const std::string& p,
434
                                            std::string* root = nullptr);
435
436
437

  /**
   * Split a path name into its basic components.  The first component
438
   * always exists and is the root returned by SplitPathRootComponent.
439
440
441
   * The remaining components form the path.  If there is a trailing
   * slash then the last component is the empty string.  The
   * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to
442
443
444
   * produce the original path.  Home directory references are
   * automatically expanded if expand_home_dir is true and this
   * platform supports them.
445
446
447
448
   *
   * This does *not* normalize the input path.  All components are
   * preserved, including empty ones.  Typically callers should use
   * this only on paths that have already been normalized.
449
   */
450
  static void SplitPath(const std::string& p,
Brad King's avatar
Brad King committed
451
                        std::vector<std::string>& components,
452
                        bool expand_home_dir = true);
453
454
455
456

  /**
   * Join components of a path name into a single string.  See
   * SplitPath for the format of the components.
457
458
459
460
   *
   * This does *not* normalize the input path.  All components are
   * preserved, including empty ones.  Typically callers should use
   * this only on paths that have already been normalized.
461
   */
462
463
464
  static std::string JoinPath(const std::vector<std::string>& components);
  static std::string JoinPath(std::vector<std::string>::const_iterator first,
                              std::vector<std::string>::const_iterator last);
465

Brad King's avatar
Brad King committed
466
467
468
  /**
   * Compare a path or components of a path.
   */
Brad King's avatar
Brad King committed
469
  static bool ComparePath(const std::string& c1, const std::string& c2);
Brad King's avatar
Brad King committed
470

471
472
473
  /**
   * Return path of a full filename (no trailing slashes)
   */
Brad King's avatar
Brad King committed
474
  static std::string GetFilenamePath(const std::string&);
475

476
477
478
  /**
   * Return file name of a full filename (i.e. file name without path)
   */
Brad King's avatar
Brad King committed
479
  static std::string GetFilenameName(const std::string&);
480

481
482
483
  /**
   * Return longest file extension of a full filename (dot included)
   */
Brad King's avatar
Brad King committed
484
  static std::string GetFilenameExtension(const std::string&);
485

486
487
488
  /**
   * Return shortest file extension of a full filename (dot included)
   */
489
  static std::string GetFilenameLastExtension(const std::string& filename);
490

491
492
493
  /**
   * Return file name without extension of a full filename
   */
494
  static std::string GetFilenameWithoutExtension(const std::string&);
495

496
497
498
  /**
   * Return file name without its last (shortest) extension
   */
499
  static std::string GetFilenameWithoutLastExtension(const std::string&);
500

501
502
503
  /**
   * Return whether the path represents a full path (not relative)
   */
Brad King's avatar
Brad King committed
504
  static bool FileIsFullPath(const std::string&);
505
  static bool FileIsFullPath(const char*);
506

507
508
509
510
  /**
   * For windows return the short path for the given path,
   * Unix just a pass through
   */
Brad King's avatar
Brad King committed
511
  static bool GetShortPath(const std::string& path, std::string& result);
512

513
  /**
514
515
   * Read line from file. Make sure to read a full line and truncates it if
   * requested via sizeLimit. Returns true if any data were read before the
516
517
518
   * end-of-file was reached. If the has_newline argument is specified, it will
   * be true when the line read had a newline character.
   */
519
  static bool GetLineFromStream(std::istream& istr, std::string& line,
520
521
                                bool* has_newline = nullptr,
                                long sizeLimit = -1);
522

523
524
525
  /**
   * Get the parent directory of the directory or file
   */
Brad King's avatar
Brad King committed
526
  static std::string GetParentDirectory(const std::string& fileOrDir);
527

528
529
  /**
   * Check if the given file or directory is in subdirectory of dir
530
   */
531
532
  static bool IsSubDirectory(const std::string& fileOrDir,
                             const std::string& dir);
533

534
535
536
537
538
  /** -----------------------------------------------------------------
   *               File Manipulation Routines
   *  -----------------------------------------------------------------
   */

539
  /**
540
541
   * Open a file considering unicode. On Windows, if 'e' is present in
   * mode it is first discarded.
542
   */
Brad King's avatar
Brad King committed
543
  static FILE* Fopen(const std::string& file, const char* mode);
544

545
/**
546
 * Visual C++ does not define mode_t.
547
548
549
550
551
 */
#if defined(_MSC_VER)
  typedef unsigned short mode_t;
#endif

552
553
554
  /**
   * Make a new directory if it is not there.  This function
   * can make a full path even if none of the directories existed
555
   * prior to calling this function.
556
   */
557
558
559
  static bool MakeDirectory(const char* path, const mode_t* mode = nullptr);
  static bool MakeDirectory(const std::string& path,
                            const mode_t* mode = nullptr);
560
561
562

  /**
   * Copy the source file to the destination file only
563
   * if the two files differ.
564
   */
Brad King's avatar
Brad King committed
565
566
  static bool CopyFileIfDifferent(const std::string& source,
                                  const std::string& destination);
567

568
569
570
  /**
   * Compare the contents of two files.  Return true if different
   */
571
572
  static bool FilesDiffer(const std::string& source,
                          const std::string& destination);
573

574
575
576
577
578
579
580
  /**
   * Compare the contents of two files, ignoring line ending differences.
   * Return true if different
   */
  static bool TextFilesDiffer(const std::string& path1,
                              const std::string& path2);

581
582
583
584
585
586
587
588
589
590
591
  /**
   * Blockwise copy source to destination file
   */
  static bool CopyFileContentBlockwise(const std::string& source,
                                       const std::string& destination);
  /**
   * Clone the source file to the destination file
   */
  static bool CloneFileContent(const std::string& source,
                               const std::string& destination);

592
593
594
  /**
   * Return true if the two files are the same file
   */
Brad King's avatar
Brad King committed
595
  static bool SameFile(const std::string& file1, const std::string& file2);
596

597
  /**
598
   * Copy a file.
599
   */
600
601
  static bool CopyFileAlways(const std::string& source,
                             const std::string& destination);
602
603

  /**
604
605
   * Copy a file.  If the "always" argument is true the file is always
   * copied.  If it is false, the file is copied only if it is new or
606
   * has changed.
607
   */
608
609
  static bool CopyAFile(const std::string& source,
                        const std::string& destination, bool always = true);
610
611
612
613
614
615
616

  /**
   * Copy content directory to another directory with all files and
   * subdirectories.  If the "always" argument is true all files are
   * always copied.  If it is false, only files that have changed or
   * are new are copied.
   */
617
618
  static bool CopyADirectory(const std::string& source,
                             const std::string& destination,
619
                             bool always = true);
620

621
622
623
  /**
   * Remove a file
   */
624
  static Status RemoveFile(std::string const& source);
625

626
627
628
  /**
   * Remove a directory
   */
629
  static Status RemoveADirectory(std::string const& source);
630

631
632
633
634
635
  /**
   * Get the maximum full file path length
   */
  static size_t GetMaximumFilePathLength();

636
637
638
  /**
   * Find a file in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
639
640
  static std::string FindFile(
    const std::string& name,
641
    const std::vector<std::string>& path = std::vector<std::string>(),
642
643
644
645
646
    bool no_system_path = false);

  /**
   * Find a directory in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
647
648
  static std::string FindDirectory(
    const std::string& name,
649
    const std::vector<std::string>& path = std::vector<std::string>(),
650
    bool no_system_path = false);
651
652
653
654

  /**
   * Find an executable in the system PATH, with optional extra paths
   */
Brad King's avatar
Brad King committed
655
  static std::string FindProgram(
656
    const char* name,
657
    const std::vector<std::string>& path = std::vector<std::string>(),
658
    bool no_system_path = false);
Brad King's avatar
Brad King committed
659
660
  static std::string FindProgram(
    const std::string& name,
661
    const std::vector<std::string>& path = std::vector<std::string>(),
662
    bool no_system_path = false);
Brad King's avatar
Brad King committed
663
664
  static std::string FindProgram(
    const std::vector<std::string>& names,
665
    const std::vector<std::string>& path = std::vector<std::string>(),
666
    bool no_system_path = false);
667
668
669
670

  /**
   * Find a library in the system PATH, with optional extra paths
   */
671
672
  static std::string FindLibrary(const std::string& name,
                                 const std::vector<std::string>& path);
673

674
675
676
  /**
   * Return true if the file is a directory
   */
Brad King's avatar
Brad King committed
677
  static bool FileIsDirectory(const std::string& name);
678

679
680
681
682
683
  /**
   * Return true if the file is an executable
   */
  static bool FileIsExecutable(const std::string& name);

684
685
686
  /**
   * Return true if the file is a symlink
   */
Brad King's avatar
Brad King committed
687
  static bool FileIsSymlink(const std::string& name);
688

689
690
691
692
693
  /**
   * Return true if the file is a FIFO
   */
  static bool FileIsFIFO(const std::string& name);

694
  /**
695
   * Return true if the file has a given signature (first set of bytes)
696
   */
697
698
  static bool FileHasSignature(const char* filename, const char* signature,
                               long offset = 0);
699

700
701
702
703
704
  /**
   * Attempt to detect and return the type of a file.
   * Up to 'length' bytes are read from the file, if more than 'percent_bin' %
   * of the bytes are non-textual elements, the file is considered binary,
   * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E]
Brad King's avatar
Brad King committed
705
   * range, but also \\n, \\r, \\t.
706
707
708
   * The algorithm is simplistic, and should probably check for usual file
   * extensions, 'magic' signature, unicode, etc.
   */
709
710
  enum FileTypeEnum
  {
711
712
713
714
    FileTypeUnknown,
    FileTypeBinary,
    FileTypeText
  };
715
716
717
  static SystemTools::FileTypeEnum DetectFileType(const char* filename,
                                                  unsigned long length = 256,
                                                  double percent_bin = 0.05);
718

719
720
  /**
   * Create a symbolic link if the platform supports it.  Returns whether
721
   * creation succeeded.
722
   */
723
724
  static bool CreateSymlink(const std::string& origName,
                            const std::string& newName);
725
726
727

  /**
   * Read the contents of a symbolic link.  Returns whether reading
728
   * succeeded.
729
   */
Brad King's avatar
Brad King committed
730
  static bool ReadSymlink(const std::string& newName, std::string& origName);
731

732
733
734
735
736
737
738
739
740
741
  /**
   * Try to locate the file 'filename' in the directory 'dir'.
   * If 'filename' is a fully qualified filename, the basename of the file is
   * used to check for its existence in 'dir'.
   * If 'dir' is not a directory, GetFilenamePath() is called on 'dir' to
   * get its directory first (thus, you can pass a filename as 'dir', as
   * a convenience).
   * 'filename_found' is assigned the fully qualified name/path of the file
   * if it is found (not touched otherwise).
   * If 'try_filename_dirs' is true, try to find the file using the
742
   * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt,
743
744
745
746
   * first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar
   * etc.
   * Return true if the file was found, false otherwise.
   */
747
  static bool LocateFileInDir(const char* filename, const char* dir,
Brad King's avatar
Brad King committed
748
                              std::string& filename_found,
749
750
                              int try_filename_dirs = 0);

751
752
  /** compute the relative path from local to remote.  local must
      be a directory.  remote can be a file or a directory.
753
754
755
756
757
758
      Both remote and local must be full paths.  Basically, if
      you are in directory local and you want to access the file in remote
      what is the relative path to do that.  For example:
      /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
      from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
  */
759
760
  static std::string RelativePath(const std::string& local,
                                  const std::string& remote);
761

762
763
764
  /**
   * Return file's modified time
   */
Brad King's avatar
Brad King committed
765
  static long int ModifiedTime(const std::string& filename);
766
767
768
769

  /**
   * Return file's creation time (Win32: works only for NTFS, not FAT)
   */
Brad King's avatar
Brad King committed
770
  static long int CreationTime(const std::string& filename);
771
772

  /**
773
774
775
776
777
778
   * Get and set permissions of the file.  If honor_umask is set, the umask
   * is queried and applied to the given permissions.  Returns false if
   * failure.
   *
   * WARNING:  A non-thread-safe method is currently used to get the umask
   * if a honor_umask parameter is set to true.
779
   */
780
781
782
783
784
785
  static Status GetPermissions(const char* file, mode_t& mode);
  static Status GetPermissions(std::string const& file, mode_t& mode);
  static Status SetPermissions(const char* file, mode_t mode,
                               bool honor_umask = false);
  static Status SetPermissions(std::string const& file, mode_t mode,
                               bool honor_umask = false);
786
787
788
789
790
791

  /** -----------------------------------------------------------------
   *               Time Manipulation Routines
   *  -----------------------------------------------------------------
   */

792
  /** Get current time in seconds since Posix Epoch (Jan 1, 1970).  */
793
794
795
796
797
  static double GetTime();

  /**
   * Get current date/time
   */
Brad King's avatar
Brad King committed
798
  static std::string GetCurrentDateTime(const char* format);
799

800
801
802
803
804
  /** -----------------------------------------------------------------
   *               Registry Manipulation Routines
   *  -----------------------------------------------------------------
   */

805
806
807
808
809
  /**
   * Specify access to the 32-bit or 64-bit application view of
   * registry values.  The default is to match the currently running
   * binary type.
   */
810
811
812
813
814
815
  enum KeyWOW64
  {
    KeyWOW64_Default,
    KeyWOW64_32,
    KeyWOW64_64
  };
816

817
818
819
  /**
   * Get a list of subkeys.
   */
Brad King's avatar
Brad King committed
820
821
  static bool GetRegistrySubKeys(const std::string& key,
                                 std::vector<std::string>& subkeys,
822
823
                                 KeyWOW64 view = KeyWOW64_Default);

824
825
826
  /**
   * Read a registry value
   */
827
  static bool ReadRegistryValue(const std::string& key, std::string& value,
828
                                KeyWOW64 view = KeyWOW64_Default);
829
830
831
832

  /**
   * Write a registry value
   */
833
834
  static bool WriteRegistryValue(const std::string& key,
                                 const std::string& value,
835
                                 KeyWOW64 view = KeyWOW64_Default);
836
837
838
839

  /**
   * Delete a registry value
   */
Brad King's avatar
Brad King committed
840
  static bool DeleteRegistryValue(const std::string& key,
841
                                  KeyWOW64 view = KeyWOW64_Default);
842
843
844
845
846
847
848

  /** -----------------------------------------------------------------
   *               Environment Manipulation Routines
   *  -----------------------------------------------------------------
   */

  /**
849
   *  Add the paths from the environment variable PATH to the
850
851
852
   *  string vector passed in.  If env is set then the value
   *  of env will be used instead of PATH.
   */
853
854
  static void GetPath(std::vector<std::string>& path,
                      const char* env = nullptr);
855
856
857
858
859

  /**
   * Read an environment variable
   */
  static const char* GetEnv(const char* key);
Brad King's avatar
Brad King committed
860
861
862
  static const char* GetEnv(const std::string& key);
  static bool GetEnv(const char* key, std::string& result);
  static bool GetEnv(const std::string& key, std::string& result);
863
864
  static bool HasEnv(const char* key);
  static bool HasEnv(const std::string& key);
865

Bill Hoffman's avatar
Bill Hoffman committed
866
867
  /** Put a string into the environment
      of the form var=value */
Brad King's avatar
Brad King committed
868
  static bool PutEnv(const std::string& env);
869
870
871

  /** Remove a string from the environment.
      Input is of the form "var" or "var=value" (value is ignored). */
Brad King's avatar
Brad King committed
872
  static bool UnPutEnv(const std::string& env);
Bill Hoffman's avatar
Bill Hoffman committed
873

874
875
876
  /**
   * Get current working directory CWD
   */
877
  static std::string GetCurrentWorkingDirectory();
878
879

  /**
880
   * Change directory to the directory specified
881
   */
Brad King's avatar
Brad King committed
882
  static int ChangeDirectory(const std::string& dir);
883
884
885
886

  /**
   * Get the result of strerror(errno)
   */
Brad King's avatar
Brad King committed
887
  static std::string GetLastSystemError();
888
889

  /**
890
   * When building DEBUG with MSVC, this enables a hook that prevents
891
892
893
894
895
   * error dialogs from popping up if the program is being run from
   * DART.
   */
  static void EnableMSVCDebugHook();

896
897
  /**
   * Get the width of the terminal window. The code may or may not work, so
898
   * make sure you have some reasonable defaults prepared if the code returns
899
900
901
   * some bogus size.
   */
  static int GetTerminalWidth();
902

903
#if @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP
904
905
906
  /**
   * Add an entry in the path translation table.
   */
907
908
  static void AddTranslationPath(const std::string& dir,
                                 const std::string& refdir);
909
910
911
912
913

  /**
   * If dir is different after CollapseFullPath is called,
   * Then insert it into the path translation table
   */
Brad King's avatar
Brad King committed
914
  static void AddKeepPath(const std::string& dir);
915
916
917
918

  /**
   * Update path by going through the Path Translation table;
   */
919
  static void CheckTranslationPath(std::string& path);
920
#endif
921

922
923
  /**
   * Delay the execution for a specified amount of time specified
luz.paz's avatar
luz.paz committed
924
   * in milliseconds
925
   */
Andy Cedilnik's avatar
Andy Cedilnik committed
926
927
  static void Delay(unsigned int msec);

928
  /**
929
930
931
   * Get the operating system name and version
   * This is implemented for Win32 only for the moment
   */
Brad King's avatar
Brad King committed
932
  static std::string GetOperatingSystemNameAndVersion();
933

934
935
936
937
938
939
940
941
942
  /** -----------------------------------------------------------------
   *               URL Manipulation Routines
   *  -----------------------------------------------------------------
   */

  /**
   * Parse a character string :
   *       protocol://dataglom
   * and fill protocol as appropriate.
943
   * decode the dataglom using DecodeURL if set to true.
944
945
   * Return false if the URL does not have the required form, true otherwise.
   */
946
  static bool ParseURLProtocol(const std::string& URL, std::string& protocol,
947
                               std::string& dataglom, bool decode = false);
948
949
950
951
952
953

  /**
   * Parse a string (a URL without protocol prefix) with the form:
   *  protocol://[[username[':'password]'@']hostname[':'dataport]]'/'[datapath]
   * and fill protocol, username, password, hostname, dataport, and datapath
   * when values are found.
954
   * decode all string except the protocol using DecodeUrl if set to true.
955
956
   * Return true if the string matches the format; false otherwise.
   */
957
958
959
  static bool ParseURL(const std::string& URL, std::string& protocol,
                       std::string& username, std::string& password,
                       std::string& hostname, std::string& dataport,
960
961
962
963
964
965
966
967
968
                       std::string& datapath, bool decode = false);

  /**
   * Decode the percent-encoded string from an URL or an URI
   * into their correct char values.
   * Does not perform any other sort of validation.
   * Return the decoded string
   */
  static std::string DecodeURL(const std::string& url);
969

970
private:
971
  /**
972
   * Allocate the stl map that serve as the Path Translation table.
973
974
975
976
   */
  static void ClassInitialize();

  /**
977
   * Deallocate the stl map that serve as the Path Translation table.
978
979
980
   */
  static void ClassFinalize();