ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
directory.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10#if !defined (HPP_ALIB_CAMP_DIRECTORY)
12#endif
13#if !defined (HPP_ALIB_CAMP_PROCESSINFO)
15#endif
16#if !defined (HPP_ALIB_CAMP_ENVIRONMENT)
18#endif
19
20#if defined ( _WIN32 )
21 #include <direct.h>
22#elif defined(__GLIBCXX__) || defined(__APPLE__) || defined(__ANDROID_NDK__)
23 #include <unistd.h>
24 #include <dirent.h>
25 #include <sys/stat.h>
26 #include <pwd.h>
27#else
28 #pragma message ("Unknown Platform in file: " __FILE__ )
29#endif
30
31#if !defined (HPP_ALIB_COMPATIBILITY_STD_STRINGS_IOSTREAM)
33#endif
34
35#include <fstream>
36#endif // !defined(ALIB_DOX)
37
38
39namespace alib { namespace lang::system {
40
41// #################################################################################################
42// Static variables
43// #################################################################################################
46
47// #################################################################################################
48// Change
49// #################################################################################################
50//! @cond NO_DOX
51void createTempFolderInHomeDir( const String& folderName, AString& resultPath, const NString& reasonMsg );
52void createTempFolderInHomeDir( const String& folderName, AString& resultPath, const NString& reasonMsg )
53{
54 // get home directory and set this as fallback result value
56 resultPath.Reset( homeTemp.Path );
57
58 // add given folder name and check if already exists
59 homeTemp.Path._( DirectorySeparator )._( folderName );
60 bool exists= Directory::Exists( homeTemp.Path );
61 if( !exists )
62 {
63 if( Directory::Create( homeTemp.Path ) == SystemErrors::OK )
64 {
65 exists= true;
66 NAString fileName( homeTemp.Path ); fileName._( DirectorySeparator )._( "readme.txt" );
67
68 std::ofstream file ( fileName );
69 if ( file.is_open() )
70 {
72 file << "This folder was created by \"" << pi.CmdLine
73 << "\"" << std::endl
74 << "to be used for temporary files." << std::endl;
75 file.write( reasonMsg.Buffer(), reasonMsg.Length() );
76 file << std::endl;
77 file.close();
78 }
79 }
80 }
81
82 // if existed or got created
83 if( exists )
84 resultPath.Reset( homeTemp.Path );
85}
86//! @endcond
87
89{
90 switch( special )
91 {
93 break;
95 break;
97 {
98
99 #if defined (__unix__)
100 if ( !EnvironmentVariables::Get( A_CHAR("HOME"), Path ) )
101 {
102 struct passwd* pwd = getpwuid(getuid());
103 Path.Reset( pwd ? NString( pwd->pw_dir ) : "~/" );
104 }
105
106 #elif defined(__APPLE__)
107 macos::ALIB_APPLE_OC_NSHomeDirectory( Path );
108 if ( Path.IsEmpty() )
109 {
110 struct passwd* pwd = getpwuid(getuid());
111 Path.Reset( pwd ? NString( pwd->pw_dir ) : "~/" );
112 }
113
114
115 #elif defined(_WIN32)
116 if ( !EnvironmentVariables::Get( A_CHAR("USERPROFILE"), Path ) || !Directory::Exists( Path ) )
117 {
118 EnvironmentVariables::Get( A_CHAR("HOMEDRIVE"), Path );
120 }
121 #else
122 #pragma message ("Unknown Platform in file: " __FILE__ )
123 #endif
124 }
125 break;
126
128 {
130
131 // try ".config" and "AppData/Roaming" subdirectories.
132 #if defined (__unix__)
133 Change( A_CHAR(".config") );
134 #elif defined(__APPLE__)
135 Change( A_CHAR("Library/Preferences") );
136 #elif defined(_WIN32)
137 Change( String16(A_CHAR("AppData")) << DirectorySeparator << A_CHAR("Roaming") );
138 #else
139 #pragma message ("Unknown Platform in file: " __FILE__ )
140 #endif
141 }
142 break;
143
144
146 {
147 Path.Reset( ProcessInfo::Current().ExecFilePath );
148 }
149 break;
150
152 {
153
155 {
156 #if defined (__unix__)
157 NString reasonMsg= "(The default temporary folder \"/tmp\" could not be found.)";
158 if ( Directory::Exists( A_CHAR("/tmp") ) )
159 evaluatedTempDir.Reset( A_CHAR("/tmp") );
160
161 #elif defined(__APPLE__)
162 NString reasonMsg= "(The default temporary folder \"/tmp\" could not be found.)";
163 macos::ALIB_APPLE_OC_NSTemporaryDirectory( evaluatedTempDir );
165 {
166 if ( Directory::Exists( A_CHAR("/tmp") ) )
167 evaluatedTempDir.Reset( A_CHAR("/tmp") );
168 }
169
170
171 #elif defined(_WIN32)
172 NString reasonMsg= "(Environment variables TMP and TEMP either not set or not containing valid paths.)";
173 AString testDir;
174 if ( ( EnvironmentVariables::Get( A_CHAR("TMP") , testDir ) && Directory::Exists( testDir ) )
175 || ( EnvironmentVariables::Get( A_CHAR("TEMP"), testDir ) && Directory::Exists( testDir ) ) )
176 {
177 evaluatedTempDir= testDir;
178 }
179 #else
180 #pragma message ("Unknown Platform in file: " __FILE__ )
181 #endif
182
183
185 {
186 createTempFolderInHomeDir( A_CHAR(".tmp"), evaluatedTempDir, reasonMsg );
187
188 // If this did not work, use home
190 {
193 }
194 }
195
196 }
197
198 // set path to evaluated dir name
200 }
201 break;
202
204 {
206 {
207 #if defined (__unix__)
208 NString reasonMsg= "(The default folder \"/var/tmp\" could not be found.)";
209
210 if ( Directory::Exists( A_CHAR("/var/tmp") ) )
211 evaluatedVarTempDir.Reset( A_CHAR("/var/tmp") );
212 #elif defined(__APPLE__)
213 const NString reasonMsg= "(The default folder \"/private/var/tmp\" could not be found.)";
214
215 if ( Directory::Exists( A_CHAR("/private/var/tmp") ) )
216 evaluatedVarTempDir.Reset( A_CHAR("/private/var/tmp") );
217
218 #elif defined(_WIN32)
219 const NString reasonMsg= "(Environment variables TMP and TEMP either not set or not containing valid paths.)";
220 AString testDir;
221 if ( ( EnvironmentVariables::Get( A_CHAR("TMP") , testDir ) && Directory::Exists( testDir ) )
222 || ( EnvironmentVariables::Get( A_CHAR("TEMP"), testDir ) && Directory::Exists( testDir ) ) )
223 {
224 evaluatedVarTempDir= testDir;
225 }
226 #else
227 #pragma message ("Unknown Platform in file: " __FILE__ )
228 #endif
229
230
232 {
233 createTempFolderInHomeDir( A_CHAR(".var.tmp"), evaluatedVarTempDir, reasonMsg );
234
235 // If this did not work, use home
237 {
240 }
241 }
242
243 }
244 // now path to evaluated dir name
246 }
247 break;
248 }
249}
250
251bool Directory::Change( const CString& path )
252{
253 // absolute addressing
254 if( path.CharAtStart() == DirectorySeparator )
255 {
256 if( !Directory::Exists( path ) )
257 return false;
258
259 Path.Reset( path );
260 return true;
261 }
262
263
264 // relative addressing
265 integer origLength= Path.Length();
266 Path._<false>( DirectorySeparator )
267 ._( path );
268
269 if( Directory::Exists( Path ) )
270 return true;
271
272 Path.ShortenTo( origLength );
273 return false;
274}
275
276bool Directory::Change( const StringNZT& path )
277{
278 // absolute addressing
279 if( path.CharAtStart() == DirectorySeparator )
280 {
281 integer origLength= Path.Length();
282 Path._<false>( path ).Terminate();
283
285 if( !Directory::Exists( CString(Path.Buffer() + origLength, path.Length() ) ) )
287 {
288 Path.ShortenTo( origLength );
289 return false;
290 }
291
292 Path.Reset( path );
293 return true;
294 }
295
296
297 // relative addressing
298 integer origLength= Path.Length();
299 Path._<false>( DirectorySeparator )
300 ._( path );
301
302 if( Directory::Exists( Path ) )
303 return true;
304
305 Path.ShortenTo( origLength );
306 return false;
307}
308
309
310// #################################################################################################
311// Static methods
312// #################################################################################################
313
314bool Directory::CurrentDirectory( AString& target ) // static
315{
316 target.Reset();
317 nchar charBuf[FILENAME_MAX];
318
319 #if defined(__GLIBCXX__) || defined(__APPLE__) || defined(__ANDROID_NDK__)
320 if ( ! getcwd( charBuf, sizeof(charBuf ) ) )
321 #elif defined ( _WIN32 )
322 if ( !_getcwd( charBuf, sizeof(charBuf ) ) )
323 #else
324 #pragma message ("Unknown Platform in file: " __FILE__ )
325 #endif
326 {
327 return false;
328 }
329
330 target._( static_cast<const nchar*>( charBuf ) );
331 return true;
332}
333
334bool Directory::Exists( const CString& path ) // static
335{
336 #if defined (__GLIBC__) || defined(__APPLE__) || defined(__ANDROID_NDK__)
337 ALIB_STRINGS_TO_NARROW(path,nPath,1024)
338 DIR* dir= opendir( nPath );
339 if ( dir != nullptr )
340 {
341 closedir( dir );
342 return true;
343 }
344 return false;
345
346 #elif defined(_WIN32)
347
348 #if !ALIB_CHARACTERS_WIDE
349 DWORD dwAttrib = GetFileAttributesA( path );
350 #else
351 DWORD dwAttrib = GetFileAttributesW( path );
352 #endif
353 if( dwAttrib == INVALID_FILE_ATTRIBUTES )
354 return false;
355 if ( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
356 return true;
357 return false;
358
359 #else
360 #pragma message ("Unknown Platform in file: " __FILE__ )
361 #endif
362}
363
364SystemErrors Directory::Create( const CString& path ) // static
365{
366 #if defined (__GLIBC__) || defined(__APPLE__) || defined(__ANDROID_NDK__)
367 ALIB_STRINGS_TO_NARROW(path,nPath,1024)
368 int errCode= mkdir( nPath, S_IRWXU | S_IRGRP | S_IROTH
369 | S_IXGRP | S_IXOTH );
370
371 return SystemErrors(errCode);
372
373 #elif defined(_WIN32)
374 #if !ALIB_CHARACTERS_WIDE
375 BOOL result= CreateDirectoryA( path, NULL );
376 #else
377 BOOL result= CreateDirectoryW( path, NULL );
378 #endif
379
380
381 if( result )
382 return SystemErrors::OK;
383
384 return SystemErrors( GetLastError() );
385 #else
386 #pragma message ("Unknown Platform in file: " __FILE__ )
387 #endif
388}
389
390
391
392}} // namespace [alib::lang::system]
static ALIB_API SystemErrors Create(const CString &path)
static ALIB_API bool CurrentDirectory(AString &target)
static AString evaluatedVarTempDir
ALIB_API bool Change(const CString &path)
static ALIB_API bool Exists(const CString &path)
static ALIB_API const ProcessInfo & Current()
TAString & ShortenTo(integer newLength)
Definition astring.hpp:908
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
constexpr bool IsEmpty() const
Definition string.hpp:414
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
constexpr const TChar * Buffer() const
Definition string.hpp:350
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_STRINGS_TO_NARROW( src, dest, bufSize)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
platform_specific integer
Definition integers.hpp:50
@ Keep
Chooses not no clear existing data.
Definition alib.cpp:57
lang::system::ProcessInfo ProcessInfo
Type alias in namespace alib.
strings::TAString< nchar > NAString
Type alias in namespace alib.
constexpr nchar DirectorySeparator
lang::system::Directory Directory
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TCString< character > CString
Type alias in namespace alib.
strings::TAString< character > AString
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
LocalString< 16 > String16
Type alias name for TLocalString<character,16> .
static ALIB_API bool Get(const CString &varName, AString &target, lang::CurrentData targetData=lang::CurrentData::Clear)