Coverage Report

Created: 2026-09-14 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/build-dir/Source/cmsys/SystemTools.hxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
3
#ifndef cmsys_SystemTools_hxx
4
#define cmsys_SystemTools_hxx
5
6
#include <cmsys/Configure.hxx>
7
#include <cmsys/Status.hxx>
8
9
#include <ctime>
10
#include <iosfwd>
11
#include <map>
12
#include <string>
13
#include <vector>
14
15
#include <sys/types.h>
16
// include sys/stat.h after sys/types.h
17
#include <sys/stat.h>
18
19
#if !defined(_WIN32) || defined(__CYGWIN__)
20
#  include <unistd.h> // For access permissions for use with access()
21
#endif
22
23
// Required for va_list
24
#include <stdarg.h>
25
// Required for FILE*
26
#include <stdio.h>
27
#if !defined(va_list)
28
// Some compilers move va_list into the std namespace and there is no way to
29
// tell that this has been done. Playing with things being included before or
30
// after stdarg.h does not solve things because we do not have control over
31
// what the user does. This hack solves this problem by moving va_list to our
32
// own namespace that is local for kwsys.
33
namespace std {
34
} // Required for platforms that do not have std namespace
35
namespace cmsys_VA_LIST {
36
using namespace std;
37
typedef va_list hack_va_list;
38
}
39
namespace cmsys {
40
typedef cmsys_VA_LIST::hack_va_list va_list;
41
}
42
#endif // va_list
43
44
namespace cmsys {
45
46
#ifdef _WIN32
47
class SystemToolsStatic;
48
#endif
49
50
#if defined(__VMS) || defined(_WIN32)
51
#  define cmsys_NEED_SYSTEM_TOOLS_MANAGER 1
52
#else
53
#  define cmsys_NEED_SYSTEM_TOOLS_MANAGER 0
54
#endif
55
56
#if cmsys_NEED_SYSTEM_TOOLS_MANAGER
57
/** \class SystemToolsManager
58
 * \brief Use to make sure SystemTools is initialized before it is used
59
 * and is the last static object destroyed
60
 */
61
class cmsys_EXPORT SystemToolsManager
62
{
63
public:
64
  SystemToolsManager();
65
  ~SystemToolsManager();
66
67
  SystemToolsManager(SystemToolsManager const&) = delete;
68
  SystemToolsManager& operator=(SystemToolsManager const&) = delete;
69
};
70
71
// This instance will show up in any translation unit that uses
72
// SystemTools. It will make sure SystemTools is initialized
73
// before it is used and is the last static object destroyed.
74
static SystemToolsManager SystemToolsManagerInstance;
75
#endif
76
77
// Flags for use with TestFileAccess.  Use a typedef in case any operating
78
// system in the future needs a special type.  These are flags that may be
79
// combined using the | operator.
80
typedef int TestFilePermissions;
81
#if defined(_WIN32) && !defined(__CYGWIN__)
82
// On Windows (VC), no system header defines these constants...
83
static TestFilePermissions const TEST_FILE_OK = 0;
84
static TestFilePermissions const TEST_FILE_READ = 4;
85
static TestFilePermissions const TEST_FILE_WRITE = 2;
86
static TestFilePermissions const TEST_FILE_EXECUTE = 1;
87
#else
88
// Standard POSIX constants
89
static TestFilePermissions const TEST_FILE_OK = F_OK;
90
static TestFilePermissions const TEST_FILE_READ = R_OK;
91
static TestFilePermissions const TEST_FILE_WRITE = W_OK;
92
static TestFilePermissions const TEST_FILE_EXECUTE = X_OK;
93
#endif
94
95
/** \class SystemTools
96
 * \brief A collection of useful platform-independent system functions.
97
 */
98
class cmsys_EXPORT SystemTools
99
{
100
public:
101
  /** -----------------------------------------------------------------
102
   *               String Manipulation Routines
103
   *  -----------------------------------------------------------------
104
   */
105
106
  /**
107
   * Replace symbols in str that are not valid in C identifiers as
108
   * defined by the 1999 standard, ie. anything except [A-Za-z0-9_].
109
   * They are replaced with `_' and if the first character is a digit
110
   * then an underscore is prepended.  Note that this can produce
111
   * identifiers that the standard reserves (_[A-Z].* and __.*).
112
   */
113
  static std::string MakeCidentifier(std::string const& s);
114
115
  static std::string MakeCindentifier(std::string const& s)
116
0
  {
117
0
    return MakeCidentifier(s);
118
0
  }
119
120
  /**
121
   * Replace replace all occurrences of the string in the source string.
122
   */
123
  static void ReplaceString(std::string& source, char const* replace,
124
                            char const* with);
125
  static void ReplaceString(std::string& source, std::string const& replace,
126
                            std::string const& with);
127
128
  /**
129
   * Return a capitalized string (i.e the first letter is uppercased,
130
   * all other are lowercased).
131
   */
132
  static std::string Capitalized(std::string const&);
133
134
  /**
135
   * Return a 'capitalized words' string (i.e the first letter of each word
136
   * is uppercased all other are left untouched though).
137
   */
138
  static std::string CapitalizedWords(std::string const&);
139
140
  /**
141
   * Return a 'uncapitalized words' string (i.e the first letter of each word
142
   * is lowercased all other are left untouched though).
143
   */
144
  static std::string UnCapitalizedWords(std::string const&);
145
146
  /** Return a lower-case string.  */
147
  static std::string LowerCase(std::string);
148
149
  /** Return an upper-case string.  */
150
  static std::string UpperCase(std::string);
151
152
  /**
153
   * Count char in string
154
   */
155
  static size_t CountChar(char const* str, char c);
156
157
  /**
158
   * Remove some characters from a string.
159
   * Return a pointer to the new resulting string (allocated with 'new')
160
   */
161
  static char* RemoveChars(char const* str, char const* toremove);
162
163
  /**
164
   * Remove remove all but 0->9, A->F characters from a string.
165
   * Return a pointer to the new resulting string (allocated with 'new')
166
   */
167
  static char* RemoveCharsButUpperHex(char const* str);
168
169
  /**
170
   * Replace some characters by another character in a string (in-place)
171
   * Return a pointer to string
172
   */
173
  static char* ReplaceChars(char* str, char const* toreplace,
174
                            char replacement);
175
176
  /**
177
   * Returns true if str1 starts (respectively ends) with str2
178
   */
179
  static bool StringStartsWith(char const* str1, char const* str2);
180
  static bool StringStartsWith(std::string const& str1, char const* str2);
181
  static bool StringEndsWith(char const* str1, char const* str2);
182
  static bool StringEndsWith(std::string const& str1, char const* str2);
183
184
  /**
185
   * Returns a pointer to the last occurrence of str2 in str1
186
   */
187
  static char const* FindLastString(char const* str1, char const* str2);
188
189
  /**
190
   * Make a duplicate of the string similar to the strdup C function
191
   * but use new to create the 'new' string, so one can use
192
   * 'delete' to remove it. Returns 0 if the input is empty.
193
   */
194
  static char* DuplicateString(char const* str);
195
196
  /**
197
   * Return the string cropped to a given length by removing chars in the
198
   * center of the string and replacing them with an ellipsis (...)
199
   */
200
  static std::string CropString(std::string const&, size_t max_len);
201
202
  /** split a path by separator into an array of strings, default is /.
203
      If isPath is true then the string is treated like a path and if
204
      s starts with a / then the first element of the returned array will
205
      be /, so /foo/bar will be [/, foo, bar]
206
  */
207
  static std::vector<std::string> SplitString(std::string const& s,
208
                                              char separator = '/',
209
                                              bool isPath = false);
210
  /**
211
   * Perform a case-independent string comparison
212
   */
213
  static int Strucmp(char const* s1, char const* s2);
214
215
  /**
216
   * Split a string on its newlines into multiple lines
217
   * Return false only if the last line stored had no newline
218
   */
219
  static bool Split(std::string const& s, std::vector<std::string>& l);
220
  static bool Split(std::string const& s, std::vector<std::string>& l,
221
                    char separator);
222
223
  /**
224
   * Joins a vector of strings into a single string, with separator in between
225
   * each string.
226
   */
227
  static std::string Join(std::vector<std::string> const& list,
228
                          std::string const& separator);
229
230
  /**
231
   * Return string with space added between capitalized words
232
   * (i.e. EatMyShorts becomes Eat My Shorts )
233
   * (note that IEatShorts becomes IEat Shorts)
234
   */
235
  static std::string AddSpaceBetweenCapitalizedWords(std::string const&);
236
237
  /**
238
   * Append two or more strings and produce new one.
239
   * Programmer must 'delete []' the resulting string, which was allocated
240
   * with 'new'.
241
   * Return 0 if inputs are empty or there was an error
242
   */
243
  static char* AppendStrings(char const* str1, char const* str2);
244
  static char* AppendStrings(char const* str1, char const* str2,
245
                             char const* str3);
246
247
  /**
248
   * Estimate the length of the string that will be produced
249
   * from printing the given format string and arguments.  The
250
   * returned length will always be at least as large as the string
251
   * that will result from printing.
252
   * WARNING: since va_arg is called to iterate of the argument list,
253
   * you will not be able to use this 'ap' anymore from the beginning.
254
   * It's up to you to call va_end though.
255
   */
256
  static int EstimateFormatLength(char const* format, va_list ap);
257
258
  /**
259
   * Escape specific characters in 'str'.
260
   */
261
  static std::string EscapeChars(char const* str, char const* chars_to_escape,
262
                                 char escape_char = '\\');
263
264
  /** -----------------------------------------------------------------
265
   *               Filename Manipulation Routines
266
   *  -----------------------------------------------------------------
267
   */
268
269
  /**
270
   * Replace Windows file system slashes with Unix-style slashes.
271
   */
272
  static void ConvertToUnixSlashes(std::string& path);
273
274
#ifdef _WIN32
275
  /** Calls Encoding::ToWindowsExtendedPath.  */
276
  static std::wstring ConvertToWindowsExtendedPath(std::string const&);
277
#endif
278
279
  /**
280
   * For windows this calls ConvertToWindowsOutputPath and for unix
281
   * it calls ConvertToUnixOutputPath
282
   */
283
  static std::string ConvertToOutputPath(std::string const&);
284
285
  /**
286
   * Convert the path to a string that can be used in a unix makefile.
287
   * double slashes are removed, and spaces are escaped.
288
   */
289
  static std::string ConvertToUnixOutputPath(std::string const&);
290
291
  /**
292
   * Convert the path to string that can be used in a windows project or
293
   * makefile.   Double slashes are removed if they are not at the start of
294
   * the string, the slashes are converted to windows style backslashes, and
295
   * if there are spaces in the string it is double quoted.
296
   */
297
  static std::string ConvertToWindowsOutputPath(std::string const&);
298
299
  /**
300
   * Return true if a path with the given name exists in the current directory.
301
   */
302
  static bool PathExists(std::string const& path);
303
304
  /**
305
   * Return true if a file exists in the current directory.
306
   * If isFile = true, then make sure the file is a file and
307
   * not a directory.  If isFile = false, then return true
308
   * if it is a file or a directory.  Note that the file will
309
   * also be checked for read access.  (Currently, this check
310
   * for read access is only done on POSIX systems.)
311
   */
312
  static bool FileExists(char const* filename, bool isFile);
313
  static bool FileExists(std::string const& filename, bool isFile);
314
  static bool FileExists(char const* filename);
315
  static bool FileExists(std::string const& filename);
316
317
  /**
318
   * Test if a file exists and can be accessed with the requested
319
   * permissions.  Symbolic links are followed.  Returns true if
320
   * the access test was successful.
321
   *
322
   * On POSIX systems (including Cygwin), this maps to the access
323
   * function.  On Windows systems, all existing files are
324
   * considered readable, and writable files are considered to
325
   * have the read-only file attribute cleared.
326
   */
327
  static bool TestFileAccess(char const* filename,
328
                             TestFilePermissions permissions);
329
  static bool TestFileAccess(std::string const& filename,
330
                             TestFilePermissions permissions);
331
/**
332
 * Cross platform wrapper for stat struct
333
 */
334
#if defined(_WIN32) && !defined(__CYGWIN__)
335
  typedef struct _stat64 Stat_t;
336
#else
337
  typedef struct stat Stat_t;
338
#endif
339
340
  /**
341
   * Cross platform wrapper for stat system call
342
   *
343
   * On Windows this may not work for paths longer than 250 characters
344
   * due to limitations of the underlying '_wstat64' call.
345
   */
346
  static int Stat(char const* path, Stat_t* buf);
347
  static int Stat(std::string const& path, Stat_t* buf);
348
349
  /**
350
   * Return file length
351
   */
352
  static unsigned long long FileLength(std::string const& filename);
353
354
  /**
355
     Change the modification time or create a file
356
  */
357
  static Status Touch(std::string const& filename, bool create);
358
359
  /**
360
   *  Compare file modification times.
361
   *  Return true for successful comparison and false for error.
362
   *  When true is returned, result has -1, 0, +1 for
363
   *  f1 older, same, or newer than f2.
364
   */
365
  static Status FileTimeCompare(std::string const& f1, std::string const& f2,
366
                                int* result);
367
368
  /**
369
   *  Get the file extension (including ".") needed for an executable
370
   *  on the current platform ("" for unix, ".exe" for Windows).
371
   */
372
  static char const* GetExecutableExtension();
373
374
  /**
375
   * Given the path to a program executable, get the directory part of
376
   * the path with the file stripped off.  If there is no directory
377
   * part, the empty string is returned.
378
   */
379
  static std::string GetProgramPath(std::string const&);
380
  static bool SplitProgramPath(std::string const& in_name, std::string& dir,
381
                               std::string& file, bool errorReport = true);
382
383
  /**
384
   * Given a path to a file or directory, convert it to a full path.
385
   * This collapses away relative paths relative to the cwd argument
386
   * (which defaults to the current working directory).  The full path
387
   * is returned.
388
   */
389
  static std::string CollapseFullPath(std::string const& in_path);
390
  static std::string CollapseFullPath(std::string const& in_path,
391
                                      char const* in_base);
392
  static std::string CollapseFullPath(std::string const& in_path,
393
                                      std::string const& in_base);
394
395
  /**
396
   * Get the real path for a given path, removing all symlinks.  In
397
   * the event of an error (non-existent path, permissions issue,
398
   * etc.) the original path is returned if errorMessage pointer is
399
   * nullptr.  Otherwise empty string is returned and errorMessage
400
   * contains error description.
401
   */
402
  static std::string GetRealPath(std::string const& path,
403
                                 std::string* errorMessage = nullptr);
404
405
  /**
406
   * Split a path name into its root component and the rest of the
407
   * path.  The root component is one of the following:
408
   *    "/"   = UNIX full path
409
   *    "c:/" = Windows full path (can be any drive letter)
410
   *    "c:"  = Windows drive-letter relative path (can be any drive letter)
411
   *    "//"  = Network path
412
   *    "~/"  = Home path for current user
413
   *    "~u/" = Home path for user 'u'
414
   *    ""    = Relative path
415
   *
416
   * A pointer to the rest of the path after the root component is
417
   * returned.  The root component is stored in the "root" string if
418
   * given.
419
   */
420
  static char const* SplitPathRootComponent(std::string const& p,
421
                                            std::string* root = nullptr);
422
423
  /**
424
   * Split a path name into its basic components.  The first component
425
   * always exists and is the root returned by SplitPathRootComponent.
426
   * The remaining components form the path.  If there is a trailing
427
   * slash then the last component is the empty string.  The
428
   * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to
429
   * produce the original path.  Home directory references are
430
   * automatically expanded if expand_home_dir is true and this
431
   * platform supports them.
432
   *
433
   * This does *not* normalize the input path.  All components are
434
   * preserved, including empty ones.  Typically callers should use
435
   * this only on paths that have already been normalized.
436
   */
437
  static void SplitPath(std::string const& p,
438
                        std::vector<std::string>& components,
439
                        bool expand_home_dir = true);
440
441
  /**
442
   * Join components of a path name into a single string.  See
443
   * SplitPath for the format of the components.
444
   *
445
   * This does *not* normalize the input path.  All components are
446
   * preserved, including empty ones.  Typically callers should use
447
   * this only on paths that have already been normalized.
448
   */
449
  static std::string JoinPath(std::vector<std::string> const& components);
450
  static std::string JoinPath(std::vector<std::string>::const_iterator first,
451
                              std::vector<std::string>::const_iterator last);
452
453
  /**
454
   * Compare a path or components of a path.
455
   */
456
  static bool ComparePath(std::string const& c1, std::string const& c2);
457
458
  /**
459
   * Return path of a full filename (no trailing slashes)
460
   */
461
  static std::string GetFilenamePath(std::string const&);
462
463
  /**
464
   * Return file name of a full filename (i.e. file name without path)
465
   */
466
  static std::string GetFilenameName(std::string const&);
467
468
  /**
469
   * Return longest file extension of a full filename (dot included)
470
   */
471
  static std::string GetFilenameExtension(std::string const&);
472
473
  /**
474
   * Return shortest file extension of a full filename (dot included)
475
   */
476
  static std::string GetFilenameLastExtension(std::string const& filename);
477
478
  /**
479
   * Return file name without extension of a full filename
480
   */
481
  static std::string GetFilenameWithoutExtension(std::string const&);
482
483
  /**
484
   * Return file name without its last (shortest) extension
485
   */
486
  static std::string GetFilenameWithoutLastExtension(std::string const&);
487
488
  /**
489
   * Return whether the path represents a full path (not relative)
490
   */
491
  static bool FileIsFullPath(std::string const&);
492
  static bool FileIsFullPath(char const*);
493
494
  /**
495
   * For windows return the short path for the given path,
496
   * Unix just a pass through
497
   */
498
  static Status GetShortPath(std::string const& path, std::string& result);
499
500
  /**
501
   * Read line from file. Make sure to read a full line and truncates it if
502
   * requested via sizeLimit. Returns true if any data were read before the
503
   * end-of-file was reached. If the has_newline argument is specified, it will
504
   * be true when the line read had a newline character.
505
   */
506
  static bool GetLineFromStream(
507
    std::istream& istr, std::string& line, bool* has_newline = nullptr,
508
    std::string::size_type sizeLimit = std::string::npos);
509
510
  /**
511
   * Get the parent directory of the directory or file
512
   */
513
  static std::string GetParentDirectory(std::string const& fileOrDir);
514
515
  /**
516
   * Check if the given file or directory is in subdirectory of dir
517
   */
518
  static bool IsSubDirectory(std::string const& fileOrDir,
519
                             std::string const& dir);
520
521
  /** -----------------------------------------------------------------
522
   *               File Manipulation Routines
523
   *  -----------------------------------------------------------------
524
   */
525
526
  /**
527
   * Open a file considering unicode. On Windows, if 'e' is present in
528
   * mode it is first discarded.
529
   */
530
  static FILE* Fopen(std::string const& file, char const* mode);
531
532
/**
533
 * Visual C++ does not define mode_t.
534
 */
535
#if defined(_MSC_VER)
536
  typedef unsigned short mode_t;
537
#endif
538
539
  /**
540
   * Make a new directory if it is not there.  This function
541
   * can make a full path even if none of the directories existed
542
   * prior to calling this function.
543
   */
544
  static Status MakeDirectory(char const* path, mode_t const* mode = nullptr);
545
  static Status MakeDirectory(std::string const& path,
546
                              mode_t const* mode = nullptr);
547
548
  /**
549
   * Represent the result of a file copy operation.
550
   * This is the result 'Status' and, if the operation failed,
551
   * an indication of whether the error occurred on the source
552
   * or destination path.
553
   */
554
  struct CopyStatus : public Status
555
  {
556
    enum WhichPath
557
    {
558
      NoPath,
559
      SourcePath,
560
      DestPath,
561
    };
562
0
    CopyStatus() = default;
563
    CopyStatus(Status s, WhichPath p)
564
0
      : Status(s)
565
0
      , Path(p)
566
0
    {
567
0
    }
568
    WhichPath Path = NoPath;
569
  };
570
571
  /**
572
   * Copy the source file to the destination file only
573
   * if the two files differ.
574
   */
575
  static CopyStatus CopyFileIfDifferent(std::string const& source,
576
                                        std::string const& destination);
577
578
  /**
579
   * Copy the source file to the destination file only
580
   * if the source file is newer than the destination file.
581
   */
582
  static CopyStatus CopyFileIfNewer(std::string const& source,
583
                                    std::string const& destination);
584
585
  /**
586
   * Compare the contents of two files.  Return true if different
587
   */
588
  static bool FilesDiffer(std::string const& source,
589
                          std::string const& destination);
590
591
  /**
592
   * Compare the contents of two files, ignoring line ending differences.
593
   * Return true if different
594
   */
595
  static bool TextFilesDiffer(std::string const& path1,
596
                              std::string const& path2);
597
598
  /**
599
   * Blockwise copy source to destination file
600
   */
601
  static CopyStatus CopyFileContentBlockwise(std::string const& source,
602
                                             std::string const& destination);
603
  /**
604
   * Clone the source file to the destination file
605
   */
606
  static CopyStatus CloneFileContent(std::string const& source,
607
                                     std::string const& destination);
608
609
  /**
610
   * Object encapsulating a unique identifier for a file
611
   * or directory
612
   */
613
#ifdef _WIN32
614
  class WindowsFileId
615
  {
616
  public:
617
    WindowsFileId() = default;
618
    WindowsFileId(unsigned long volumeSerialNumber,
619
                  unsigned long fileIndexHigh, unsigned long fileIndexLow);
620
621
    bool operator==(WindowsFileId const& o) const;
622
    bool operator!=(WindowsFileId const& o) const;
623
624
  private:
625
    unsigned long m_volumeSerialNumber;
626
    unsigned long m_fileIndexHigh;
627
    unsigned long m_fileIndexLow;
628
  };
629
  using FileId = WindowsFileId;
630
#else
631
  class UnixFileId
632
  {
633
  public:
634
    UnixFileId() = default;
635
    UnixFileId(dev_t volumeSerialNumber, ino_t fileSerialNumber,
636
               off_t fileSize);
637
638
    bool operator==(UnixFileId const& o) const;
639
    bool operator!=(UnixFileId const& o) const;
640
641
  private:
642
    dev_t m_volumeSerialNumber;
643
    ino_t m_fileSerialNumber;
644
    off_t m_fileSize;
645
  };
646
  using FileId = UnixFileId;
647
#endif
648
649
  /**
650
   * Outputs a FileId for the given file or directory.
651
   * Returns true on success, false on failure
652
   */
653
  static bool GetFileId(std::string const& file, FileId& id);
654
655
  /**
656
   * Return true if the two files are the same file
657
   */
658
  static bool SameFile(std::string const& file1, std::string const& file2);
659
660
  /**
661
   * Copy a file.
662
   */
663
  static CopyStatus CopyFileAlways(std::string const& source,
664
                                   std::string const& destination);
665
666
  enum class CopyWhen
667
  {
668
    Unconditional,
669
    OnlyIfDifferent,
670
    OnlyIfNewer,
671
  };
672
673
  /**
674
   * Copy a file with specified copy behavior.
675
   */
676
  static CopyStatus CopyAFile(std::string const& source,
677
                              std::string const& destination,
678
                              CopyWhen when = CopyWhen::Unconditional);
679
  static CopyStatus CopyAFile(std::string const& source,
680
                              std::string const& destination, bool always);
681
682
  /**
683
   * Copy content directory to another directory with all files and
684
   * subdirectories.  The "when" argument controls when files are copied:
685
   * Unconditional: all files are always copied.
686
   * OnlyIfDifferent: only files that have changed are copied.
687
   * OnlyIfNewer: only files that are newer than the destination are copied.
688
   */
689
  static Status CopyADirectory(std::string const& source,
690
                               std::string const& destination,
691
                               CopyWhen when = CopyWhen::Unconditional);
692
  static Status CopyADirectory(std::string const& source,
693
                               std::string const& destination, bool always);
694
695
  /**
696
   * Remove a file
697
   */
698
  static Status RemoveFile(std::string const& source);
699
700
  /**
701
   * Remove a directory
702
   */
703
  static Status RemoveADirectory(std::string const& source);
704
705
  /**
706
   * Get the maximum full file path length
707
   */
708
  static size_t GetMaximumFilePathLength();
709
710
  /**
711
   * Find a file in the system PATH, with optional extra paths
712
   */
713
  static std::string FindFile(
714
    std::string const& name,
715
    std::vector<std::string> const& path = std::vector<std::string>(),
716
    bool no_system_path = false);
717
718
  /**
719
   * Find a directory in the system PATH, with optional extra paths
720
   */
721
  static std::string FindDirectory(
722
    std::string const& name,
723
    std::vector<std::string> const& path = std::vector<std::string>(),
724
    bool no_system_path = false);
725
726
  /**
727
   * Find an executable in the system PATH, with optional extra paths
728
   */
729
  static std::string FindProgram(
730
    std::string const& name,
731
    std::vector<std::string> const& path = std::vector<std::string>(),
732
    bool no_system_path = false);
733
734
  /**
735
   * Return true if the file is a directory
736
   */
737
  static bool FileIsDirectory(std::string const& name);
738
739
  /**
740
   * Return true if the file is an executable
741
   */
742
  static bool FileIsExecutable(std::string const& name);
743
744
#if defined(_WIN32)
745
  /**
746
   * Return true if the file with FileAttributes `attr` is a symlink
747
   * Only available on Windows. This avoids an expensive `GetFileAttributesW`
748
   * call.
749
   */
750
  static bool FileIsSymlinkWithAttr(std::wstring const& path,
751
                                    unsigned long attr);
752
#endif
753
754
  /**
755
   * Return true if the file is a symlink
756
   */
757
  static bool FileIsSymlink(std::string const& name);
758
759
  /**
760
   * Return true if the file is a FIFO
761
   */
762
  static bool FileIsFIFO(std::string const& name);
763
764
  /**
765
   * Return true if the file has a given signature (first set of bytes)
766
   */
767
  static bool FileHasSignature(char const* filename, char const* signature,
768
                               long offset = 0);
769
770
  /**
771
   * Attempt to detect and return the type of a file.
772
   * Up to 'length' bytes are read from the file, if more than 'percent_bin' %
773
   * of the bytes are non-textual elements, the file is considered binary,
774
   * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E]
775
   * range, but also \\n, \\r, \\t.
776
   * The algorithm is simplistic, and should probably check for usual file
777
   * extensions, 'magic' signature, unicode, etc.
778
   */
779
  enum FileTypeEnum
780
  {
781
    FileTypeUnknown,
782
    FileTypeBinary,
783
    FileTypeText
784
  };
785
  static SystemTools::FileTypeEnum DetectFileType(char const* filename,
786
                                                  unsigned long length = 256,
787
                                                  double percent_bin = 0.05);
788
789
  /**
790
   * Read the contents of a symbolic link.  Returns whether reading
791
   * succeeded.
792
   */
793
  static Status ReadSymlink(std::string const& newName, std::string& origName);
794
795
  /**
796
   * Try to locate the file 'filename' in the directory 'dir'.
797
   * If 'filename' is a fully qualified filename, the basename of the file is
798
   * used to check for its existence in 'dir'.
799
   * If 'dir' is not a directory, GetFilenamePath() is called on 'dir' to
800
   * get its directory first (thus, you can pass a filename as 'dir', as
801
   * a convenience).
802
   * 'filename_found' is assigned the fully qualified name/path of the file
803
   * if it is found (not touched otherwise).
804
   * If 'try_filename_dirs' is true, try to find the file using the
805
   * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt,
806
   * first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar
807
   * etc.
808
   * Return true if the file was found, false otherwise.
809
   */
810
  static bool LocateFileInDir(char const* filename, char const* dir,
811
                              std::string& filename_found,
812
                              int try_filename_dirs = 0);
813
814
  /** compute the relative path from local to remote.  local must
815
      be a directory.  remote can be a file or a directory.
816
      Both remote and local must be full paths.  Basically, if
817
      you are in directory local and you want to access the file in remote
818
      what is the relative path to do that.  For example:
819
      /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
820
      from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
821
  */
822
  static std::string RelativePath(std::string const& local,
823
                                  std::string const& remote);
824
825
  /**
826
   * Return file's modified time
827
   */
828
  static long int ModifiedTime(std::string const& filename);
829
830
  /**
831
   * Return file's creation time (Win32: works only for NTFS, not FAT)
832
   */
833
  static long int CreationTime(std::string const& filename);
834
835
  /**
836
   * Get and set permissions of the file.  If honor_umask is set, the umask
837
   * is queried and applied to the given permissions.  Returns false if
838
   * failure.
839
   *
840
   * WARNING:  A non-thread-safe method is currently used to get the umask
841
   * if a honor_umask parameter is set to true.
842
   */
843
  static Status GetPermissions(char const* file, mode_t& mode);
844
  static Status GetPermissions(std::string const& file, mode_t& mode);
845
  static Status SetPermissions(char const* file, mode_t mode,
846
                               bool honor_umask = false);
847
  static Status SetPermissions(std::string const& file, mode_t mode,
848
                               bool honor_umask = false);
849
850
  /** -----------------------------------------------------------------
851
   *               Time Manipulation Routines
852
   *  -----------------------------------------------------------------
853
   */
854
855
  /** Get time as local time (thread-safe).  */
856
  static std::tm LocalTime(std::time_t timep);
857
858
  /** Get time as UTC time (thread-safe).  */
859
  static std::tm GMTime(std::time_t timep);
860
861
  /** Get current time in seconds since Posix Epoch (Jan 1, 1970).  */
862
  static double GetTime();
863
864
  /**
865
   * Get current date/time
866
   */
867
  static std::string GetCurrentDateTime(char const* format);
868
869
  /** -----------------------------------------------------------------
870
   *               Registry Manipulation Routines
871
   *  -----------------------------------------------------------------
872
   */
873
874
  /**
875
   * Specify access to the 32-bit or 64-bit application view of
876
   * registry values.  The default is to match the currently running
877
   * binary type.
878
   */
879
  enum KeyWOW64
880
  {
881
    KeyWOW64_Default,
882
    KeyWOW64_32,
883
    KeyWOW64_64
884
  };
885
886
  /**
887
   * Get a list of subkeys.
888
   */
889
  static bool GetRegistrySubKeys(std::string const& key,
890
                                 std::vector<std::string>& subkeys,
891
                                 KeyWOW64 view = KeyWOW64_Default);
892
893
  /**
894
   * Read a registry value
895
   */
896
  static bool ReadRegistryValue(std::string const& key, std::string& value,
897
                                KeyWOW64 view = KeyWOW64_Default);
898
899
  /**
900
   * Write a registry value
901
   */
902
  static bool WriteRegistryValue(std::string const& key,
903
                                 std::string const& value,
904
                                 KeyWOW64 view = KeyWOW64_Default);
905
906
  /**
907
   * Delete a registry value
908
   */
909
  static bool DeleteRegistryValue(std::string const& key,
910
                                  KeyWOW64 view = KeyWOW64_Default);
911
912
  /** -----------------------------------------------------------------
913
   *               Environment Manipulation Routines
914
   *  -----------------------------------------------------------------
915
   */
916
917
  /**
918
   *  Add the paths from the environment variable PATH to the
919
   *  string vector passed in.  If env is set then the value
920
   *  of env will be used instead of PATH.
921
   */
922
  static void GetPath(std::vector<std::string>& path,
923
                      char const* env = nullptr);
924
925
  /**
926
   * Read an environment variable
927
   */
928
  static char const* GetEnv(char const* key);
929
  static char const* GetEnv(std::string const& key);
930
  static bool GetEnv(char const* key, std::string& result);
931
  static bool GetEnv(std::string const& key, std::string& result);
932
  static bool HasEnv(char const* key);
933
  static bool HasEnv(std::string const& key);
934
935
  /** Put a string into the environment
936
      of the form var=value */
937
  static bool PutEnv(std::string const& env);
938
939
  /** Remove a string from the environment.
940
      Input is of the form "var" or "var=value" (value is ignored). */
941
  static bool UnPutEnv(std::string const& env);
942
943
  /**
944
   * Get current working directory CWD
945
   */
946
  static std::string GetCurrentWorkingDirectory();
947
948
  /**
949
   * Change directory to the directory specified
950
   */
951
  static Status ChangeDirectory(std::string const& dir);
952
953
  /**
954
   * Get the result of strerror(errno)
955
   */
956
  static std::string GetLastSystemError();
957
958
  /**
959
   * When building DEBUG with MSVC, this enables a hook that prevents
960
   * error dialogs from popping up if the program is being run from
961
   * DART.
962
   */
963
  static void EnableMSVCDebugHook();
964
965
  /**
966
   * Get the width of the terminal window. The code may or may not work, so
967
   * make sure you have some reasonable defaults prepared if the code returns
968
   * some bogus size.
969
   */
970
  static int GetTerminalWidth();
971
972
  /**
973
   * Delay the execution for a specified amount of time specified
974
   * in milliseconds
975
   */
976
  static void Delay(unsigned int msec);
977
978
  /**
979
   * Get the operating system name and version
980
   * This is implemented for Win32 only for the moment
981
   */
982
  static std::string GetOperatingSystemNameAndVersion();
983
984
  /** -----------------------------------------------------------------
985
   *               URL Manipulation Routines
986
   *  -----------------------------------------------------------------
987
   */
988
989
  /**
990
   * Parse a character string :
991
   *       protocol://dataglom
992
   * and fill protocol as appropriate.
993
   * decode the dataglom using DecodeURL if set to true.
994
   * Return false if the URL does not have the required form, true otherwise.
995
   */
996
  static bool ParseURLProtocol(std::string const& URL, std::string& protocol,
997
                               std::string& dataglom, bool decode = false);
998
999
  /**
1000
   * Parse a string (a URL without protocol prefix) with the form:
1001
   *  protocol://[[username[':'password]'@']hostname[':'dataport]]'/'[datapath]
1002
   * and fill protocol, username, password, hostname, dataport, and datapath
1003
   * when values are found.
1004
   * decode all string except the protocol using DecodeUrl if set to true.
1005
   * Return true if the string matches the format; false otherwise.
1006
   */
1007
  static bool ParseURL(std::string const& URL, std::string& protocol,
1008
                       std::string& username, std::string& password,
1009
                       std::string& hostname, std::string& dataport,
1010
                       std::string& datapath, bool decode = false);
1011
1012
  /**
1013
   * Decode the percent-encoded string from an URL or an URI
1014
   * into their correct char values.
1015
   * Does not perform any other sort of validation.
1016
   * Return the decoded string
1017
   */
1018
  static std::string DecodeURL(std::string const& url);
1019
1020
private:
1021
#if cmsys_NEED_SYSTEM_TOOLS_MANAGER
1022
  static void ClassInitialize();
1023
  static void ClassFinalize();
1024
1025
  /**
1026
   * This method prevents warning on SGI
1027
   */
1028
  SystemToolsManager* GetSystemToolsManager()
1029
  {
1030
    return &SystemToolsManagerInstance;
1031
  }
1032
#endif
1033
1034
  static void ReplaceStringImpl(std::string& source, char const* replace,
1035
                                size_t replaceSize, std::string const& with);
1036
  /**
1037
   * Find a filename (file or directory) in the system PATH, with
1038
   * optional extra paths.
1039
   */
1040
  static std::string FindNameImpl(
1041
    std::string const& name,
1042
    std::vector<std::string> const& userPaths = std::vector<std::string>(),
1043
    bool no_system_path = false);
1044
1045
#ifdef _WIN32
1046
  friend class SystemToolsStatic;
1047
#endif
1048
#if cmsys_NEED_SYSTEM_TOOLS_MANAGER
1049
  friend class SystemToolsManager;
1050
#endif
1051
};
1052
1053
} // namespace cmsys
1054
1055
#endif