4#include "Stroika/Foundation/StroikaPreComp.h"
6#if qStroika_Foundation_Common_Platform_Linux
10#elif qStroika_Foundation_Common_Platform_MacOS
12#elif qStroika_Foundation_Common_Platform_Windows
29#include "FileSystem.h"
38using namespace Stroika::Foundation::IO;
44#if qStroika_Foundation_Common_Platform_Linux
47 struct Watcher_Proc_Mounts_ {
49 Watcher_Proc_Mounts_ (
const filesystem::path& fn)
50 : mfd{::open (fn.c_str (), O_RDONLY, 0)}
53 ~Watcher_Proc_Mounts_ ()
57 bool IsNewAvail ()
const
70 pfd.events = POLLERR | POLLPRI;
72 if ((rv = ::poll (&pfd, 1, 0)) >= 0) {
73 if (pfd.revents & POLLERR) {
83#if qStroika_Foundation_Common_Platform_MacOS
91 [[maybe_unused]] lock_guard critSec{sMutex_};
92 [[maybe_unused]]
auto&& cleanup =
Execution::Finally ([&] ()
noexcept { ::endfsent (); });
93 while (fstab* fs = ::getfsent ()) {
125#if USE_NOISY_TRACE_IN_THIS_MODULE_
126 DbgTrace (
"in IO::FileSystem::{}::ReadMountInfo_MTabLikeFile_ linesize={}, line[0]={}"_f, line.size (), line.empty () ?
""_k : line[0]);
135 if (line.size () >= 3) {
140 IgnoreExceptionsExceptThreadAbortForCall (devName =
String{filesystem::canonical (devName.
As<filesystem::path> ())});
142 filesystem::path mountedAt = line[1].As<filesystem::path> ();
144 static const String kNone_{L
"none"sv};
152#if qStroika_Foundation_Common_Platform_Linux
157 static const filesystem::path kUseFile2List_{
"/proc/mounts"};
158 static const Watcher_Proc_Mounts_ sWatcher_{kUseFile2List_};
161 static bool sFirstTime_{
true};
162 if (sFirstTime_ or sWatcher_.IsNewAvail ()) {
163 sLastResult_ = ReadMountInfo_MTabLikeFile_ (FileInputStream::New (kUseFile2List_, IO::FileSystem::FileInputStream::eNotSeekable));
170#if qStroika_Foundation_Common_Platform_Linux
175 static const filesystem::path kUseFile2List_{
"/etc/mtab"};
176 return ReadMountInfo_MTabLikeFile_ (FileInputStream::New (kUseFile2List_, IO::FileSystem::FileInputStream::eNotSeekable));
180#if qStroika_Foundation_Common_Platform_Windows
182 using DynamicDiskIDType_ = filesystem::path;
183 DynamicDiskIDType_ GetPhysNameForDriveNumber_ (
unsigned int i)
188 return "\\\\.\\PhysicalDrive{}"_f(i).As<filesystem::path> ();
191 optional<
Set<DynamicDiskIDType_>> GetDisksForVolume_ (
String volumeName)
193 wchar_t volPathsBuf[10 * 1024];
196 DWORD x = ::GetVolumePathNamesForVolumeNameW (get<0> (volumeName.c_str (&buf)), volPathsBuf,
197 static_cast<DWORD
> (Memory::NEltsOf (volPathsBuf)), &retLen);
201 else if (retLen <= 1) {
204 Assert (1 <= Characters::CString::Length (volPathsBuf) and Characters::CString::Length (volPathsBuf) < Memory::NEltsOf (volPathsBuf));
205 volumeName = L
"\\\\.\\" + String::FromSDKString (volPathsBuf).SubString (0, -1);
208 VOLUME_DISK_EXTENTS volumeDiskExtents;
214 HANDLE hHandle = ::CreateFileW (volumeName.As<wstring> ().c_str (), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
215 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr);
216 if (hHandle == INVALID_HANDLE_VALUE) {
219 DWORD dwBytesReturned = 0;
220 BOOL bResult = ::DeviceIoControl (hHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0, &volumeDiskExtents,
221 sizeof (volumeDiskExtents), &dwBytesReturned, NULL);
222 ::CloseHandle (hHandle);
228 for (DWORD n = 0; n < volumeDiskExtents.NumberOfDiskExtents; ++n) {
229 result.
Add (GetPhysNameForDriveNumber_ (volumeDiskExtents.Extents[n].DiskNumber));
233 DISABLE_COMPILER_MSC_WARNING_END (6262)
240 TCHAR volumeNameBuf[1024];
242 HANDLE hVol = INVALID_HANDLE_VALUE;
244 if (hVol != INVALID_HANDLE_VALUE) {
245 ::CloseHandle (hVol);
249 for (hVol = ::FindFirstVolume (volumeNameBuf,
static_cast<DWORD
> (Memory::NEltsOf (volumeNameBuf))); hVol != INVALID_HANDLE_VALUE;) {
250 DWORD lpMaximumComponentLength;
252 TCHAR fileSysNameBuf[1024];
253 if (::GetVolumeInformation (volumeNameBuf,
nullptr,
static_cast<DWORD
> (Memory::NEltsOf (volumeNameBuf)),
nullptr, &lpMaximumComponentLength,
254 &dwSysFlags, fileSysNameBuf,
static_cast<DWORD
> (Memory::NEltsOf (fileSysNameBuf)))) {
257 v.
fVolumeID = String::FromSDKString (volumeNameBuf);
260 TCHAR volPathsBuf[10 * 1024];
262 DWORD x = ::GetVolumePathNamesForVolumeName (volumeNameBuf, volPathsBuf,
static_cast<DWORD
> (Memory::NEltsOf (volPathsBuf)), &retLen);
264 DbgTrace (
"Ignoring error getting paths (volume='{}')"_f, String::FromSDKString (volumeNameBuf));
266 else if (volPathsBuf[0] == 0) {
268 DbgTrace (
"Ignoring unmounted filesystem (volume='{}')"_f, String::FromSDKString (volumeNameBuf));
271 for (
const TCHAR* NameIdx = volPathsBuf; NameIdx[0] != L
'\0'; NameIdx += Characters::CString::Length (NameIdx) + 1) {
279 if (not::FindNextVolume (hVol, volumeNameBuf,
static_cast<DWORD
> (Memory::NEltsOf (volumeNameBuf)))) {
280 ::FindVolumeClose (hVol);
281 hVol = INVALID_HANDLE_VALUE;
286 DISABLE_COMPILER_MSC_WARNING_END (6262)
320#if qStroika_Foundation_Common_Platform_Linux
321 return ReadMountInfo_FromProcFSMounts_ ();
322#elif qStroika_Foundation_Common_Platform_MacOS
323 return ReadMountInfo_getfsent_ ();
324#elif qStroika_Foundation_Common_Platform_Windows
325 return GetMountedFilesystems_Windows_ ();
#define WeakAssertNotImplemented()
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual bool StartsWith(const Character &c, CompareOptions co=eWithCase) const
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
a cross between Mapping<KEY, T> and Collection<T> and Set<T>
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
This COULD be easily used to read CSV files, or tab-delimited files, for example.
Wrap any object with Synchronized<> and it can be used similarly to the base type,...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual CONTAINER_OF_T As(CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
DISABLE_COMPILER_MSC_WARNING_START(4996)
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
Containers::KeyedCollection< MountedFilesystemType, filesystem::path > GetMountedFilesystems()
optional< String > fVolumeID
nonvirtual String ToString() const
optional< Containers::Set< filesystem::path > > fDevicePaths
filesystem::path fMountedOn
optional< String > fFileSystemType