Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Foundation/IO/FileSystem/Filesystem.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#if qStroika_Foundation_Common_Platform_Windows
7#include <windows.h>
8
9#include <shellapi.h>
10#include <shlobj.h>
11#elif qStroika_Foundation_Common_Platform_POSIX
12#include <sys/stat.h>
13#include <sys/types.h>
14#include <unistd.h>
15#endif
16#if qStroika_Foundation_Common_Platform_Linux
17#include <linux/limits.h>
18#endif
21#include "Stroika/Foundation/Containers/Collection.h"
22#include "Stroika/Foundation/Containers/Set.h"
24#if qStroika_Foundation_Common_Platform_Windows
25#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
26#include "Stroika/Foundation/Execution/Platform/Windows/HRESULTErrorException.h"
27#endif
28#include "Stroika/Foundation/Execution/Exceptions.h"
30
32
33#include "DirectoryIterable.h"
34#include "FileUtils.h"
35
36#include "FileSystem.h"
37
38using namespace Stroika::Foundation;
41using namespace Stroika::Foundation::Execution;
42using namespace Stroika::Foundation::IO;
44
45#if qStroika_Foundation_Common_Platform_Windows
47#endif
48
49// Comment this in to turn on aggressive noisy DbgTrace in this module
50// #define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
51
52/*
53 ********************************************************************************
54 ********************************** FileSystem::Ptr *****************************
55 ********************************************************************************
56 */
57bool IO::FileSystem::Ptr::Access (const filesystem::path& fileFullPath, AccessMode accessMode) const noexcept
58{
59// @todo FIX to only do ONE system call, not two!!!
60#if qStroika_Foundation_Common_Platform_POSIX
61 // Not REALLY right - but an OK hack for now... -- LGP 2011-09-26
62 //http://linux.die.net/man/2/access
63 if ((accessMode & AccessMode::eRead) == AccessMode::eRead) {
64 if (access (fileFullPath.c_str (), R_OK) != 0) {
65 return false;
66 }
67 }
68 if ((accessMode & AccessMode::eWrite) == AccessMode::eWrite) {
69 if (access (fileFullPath.c_str (), W_OK) != 0) {
70 return false;
71 }
72 }
73 return true;
74#elif qStroika_Foundation_Common_Platform_Windows
75 if ((accessMode & AccessMode::eRead) == AccessMode::eRead) {
76 DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
77 if (attribs == INVALID_FILE_ATTRIBUTES) {
78 return false;
79 }
80 }
81 if ((accessMode & AccessMode::eWrite) == AccessMode::eWrite) {
82 DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
83 if ((attribs == INVALID_FILE_ATTRIBUTES) or (attribs & FILE_ATTRIBUTE_READONLY)) {
84 return false;
85 }
86 }
87 return true;
88#else
90 return false;
91#endif
92}
93
94void IO::FileSystem::Ptr::CheckAccess (const filesystem::path& fileFullPath, AccessMode accessMode)
95{
96 // quick hack - not fully implemented - but since advsiory only - not too important...
97 if (not Access (fileFullPath, accessMode)) {
98 // @todo take into account 'accessMode' in the resulting message
99 Execution::Throw (IO::FileSystem::Exception{make_error_code (errc::permission_denied), fileFullPath});
100 }
101}
102
103void IO::FileSystem::Ptr::CheckAccess (const filesystem::path& fileFullPath, bool checkCanRead, bool checkCanWrite)
104{
105 if (checkCanRead and checkCanWrite) {
106 CheckAccess (fileFullPath, IO::AccessMode::eReadWrite);
107 }
108 else if (checkCanRead) {
109 CheckAccess (fileFullPath, IO::AccessMode::eRead);
110 }
111 else if (checkCanWrite) {
112 CheckAccess (fileFullPath, IO::AccessMode::eWrite);
113 }
114}
115
116DateTime IO::FileSystem::Ptr::GetFileLastModificationDate (const filesystem::path& fileName)
117{
118#if qStroika_Foundation_Common_Platform_POSIX
119 struct stat s{};
120 FileSystem::Exception::ThrowPOSIXErrNoIfNegative (::stat (fileName.generic_string ().c_str (), &s), fileName);
121 return DateTime{s.st_mtime};
122#elif qStroika_Foundation_Common_Platform_Windows
123 WIN32_FILE_ATTRIBUTE_DATA fileAttrData{};
124 FileSystem::Exception::ThrowIfZeroGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData), fileName);
125 return DateTime{fileAttrData.ftLastWriteTime};
126#else
128 return DateTime{};
129#endif
130}
131
132DateTime IO::FileSystem::Ptr::GetFileLastAccessDate (const filesystem::path& fileName)
133{
134#if qStroika_Foundation_Common_Platform_POSIX
135 struct stat s{};
136 FileSystem::Exception::ThrowPOSIXErrNoIfNegative (::stat (fileName.generic_string ().c_str (), &s), fileName);
137 return DateTime{s.st_atime};
138#elif qStroika_Foundation_Common_Platform_Windows
139 WIN32_FILE_ATTRIBUTE_DATA fileAttrData{};
140 FileSystem::Exception::ThrowIfZeroGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData), fileName);
141 return DateTime{fileAttrData.ftLastAccessTime};
142#else
144 return DateTime{};
145#endif
146}
147
148/*
149 ********************************************************************************
150 **************************** FileSystem::Default *******************************
151 ********************************************************************************
152 */
154{
155 static IO::FileSystem::Ptr sThe_;
156 return sThe_;
157}
#define AssertNotImplemented()
Definition Assertions.h:401
static INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode, const path &p1={}, const path &p2={})
nonvirtual void CheckAccess(const filesystem::path &fileFullPath, AccessMode accessMode=AccessMode::eRead)
nonvirtual bool Access(const filesystem::path &fileFullPath, AccessMode accessMode=AccessMode::eRead) const noexcept
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43