Coverage Report

Created: 2026-03-12 06:35

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