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