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
37using namespace Stroika::Foundation::IO;
43#if qStroika_Foundation_Common_Platform_Linux
46 struct Watcher_Proc_Mounts_ {
48 Watcher_Proc_Mounts_ (
const filesystem::path& fn)
49 : mfd{::open (fn.c_str (), O_RDONLY, 0)}
52 ~Watcher_Proc_Mounts_ ()
56 bool IsNewAvail ()
const
69 pfd.events = POLLERR | POLLPRI;
71 if ((rv = ::poll (&pfd, 1, 0)) >= 0) {
72 if (pfd.revents & POLLERR) {
82#if qStroika_Foundation_Common_Platform_MacOS
90 [[maybe_unused]] lock_guard critSec{sMutex_};
91 [[maybe_unused]]
auto&& cleanup = Execution::Finally ([&] ()
noexcept { ::endfsent (); });
92 while (fstab* fs = ::getfsent ()) {
124#if USE_NOISY_TRACE_IN_THIS_MODULE_
125 DbgTrace (
"in IO::FileSystem::{}::ReadMountInfo_MTabLikeFile_ linesize={}, line[0]={}"_f, line.size (), line.empty () ?
""_k : line[0]);
134 if (line.size () >= 3) {
139 IgnoreExceptionsExceptThreadAbortForCall (devName =
String{filesystem::canonical (devName.
As<filesystem::path> ())});
141 filesystem::path mountedAt = line[1].As<filesystem::path> ();
143 static const String kNone_{
"none"sv};
151#if qStroika_Foundation_Common_Platform_Linux
156 static const filesystem::path kUseFile2List_{
"/proc/mounts"};
157 static const Watcher_Proc_Mounts_ sWatcher_{kUseFile2List_};
160 static bool sFirstTime_{
true};
161 if (sFirstTime_ or sWatcher_.IsNewAvail ()) {
162 sLastResult_ = ReadMountInfo_MTabLikeFile_ (FileInputStream::New (kUseFile2List_, IO::FileSystem::FileInputStream::eNotSeekable));
169#if qStroika_Foundation_Common_Platform_Linux
174 static const filesystem::path kUseFile2List_{
"/etc/mtab"};
175 return ReadMountInfo_MTabLikeFile_ (FileInputStream::New (kUseFile2List_, IO::FileSystem::FileInputStream::eNotSeekable));
179#if qStroika_Foundation_Common_Platform_Windows
181 using DynamicDiskIDType_ = filesystem::path;
182 DynamicDiskIDType_ GetPhysNameForDriveNumber_ (
unsigned int i)
187 return "\\\\.\\PhysicalDrive{}"_f(i).As<filesystem::path> ();
190 optional<
Set<DynamicDiskIDType_>> GetDisksForVolume_ (
String volumeName)
192 wchar_t volPathsBuf[10 * 1024];
195 DWORD x = ::GetVolumePathNamesForVolumeNameW (get<0> (volumeName.c_str (&buf)), volPathsBuf,
196 static_cast<DWORD
> (std::size (volPathsBuf)), &retLen);
200 else if (retLen <= 1) {
203 Assert (1 <= Characters::CString::Length (volPathsBuf) and Characters::CString::Length (volPathsBuf) < std::size (volPathsBuf));
204 volumeName =
"\\\\.\\"sv + String::FromSDKString (volPathsBuf).SubString (0, -1);
207 VOLUME_DISK_EXTENTS volumeDiskExtents;
213 HANDLE hHandle = ::CreateFileW (volumeName.As<wstring> ().c_str (), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
214 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr);
215 if (hHandle == INVALID_HANDLE_VALUE) {
218 DWORD dwBytesReturned = 0;
219 BOOL bResult = ::DeviceIoControl (hHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0, &volumeDiskExtents,
220 sizeof (volumeDiskExtents), &dwBytesReturned, NULL);
221 ::CloseHandle (hHandle);
227 for (DWORD n = 0; n < volumeDiskExtents.NumberOfDiskExtents; ++n) {
228 result.
Add (GetPhysNameForDriveNumber_ (volumeDiskExtents.Extents[n].DiskNumber));
232 DISABLE_COMPILER_MSC_WARNING_END (6262)
239 TCHAR volumeNameBuf[1024];
241 HANDLE hVol = INVALID_HANDLE_VALUE;
242 [[maybe_unused]]
auto&& cleanup = Execution::Finally ([&] ()
noexcept {
243 if (hVol != INVALID_HANDLE_VALUE) {
244 ::CloseHandle (hVol);
248 for (hVol = ::FindFirstVolume (volumeNameBuf,
static_cast<DWORD
> (std::size (volumeNameBuf))); hVol != INVALID_HANDLE_VALUE;) {
249 DWORD lpMaximumComponentLength;
251 TCHAR fileSysNameBuf[1024];
252 if (::GetVolumeInformation (volumeNameBuf,
nullptr,
static_cast<DWORD
> (std::size (volumeNameBuf)),
nullptr, &lpMaximumComponentLength,
253 &dwSysFlags, fileSysNameBuf,
static_cast<DWORD
> (std::size (fileSysNameBuf)))) {
256 v.
fVolumeID = String::FromSDKString (volumeNameBuf);
259 TCHAR volPathsBuf[10 * 1024];
261 DWORD x = ::GetVolumePathNamesForVolumeName (volumeNameBuf, volPathsBuf,
static_cast<DWORD
> (std::size (volPathsBuf)), &retLen);
263 DbgTrace (
"Ignoring error getting paths (volume='{}')"_f, String::FromSDKString (volumeNameBuf));
265 else if (volPathsBuf[0] == 0) {
267 DbgTrace (
"Ignoring unmounted filesystem (volume='{}')"_f, String::FromSDKString (volumeNameBuf));
270 for (
const TCHAR* NameIdx = volPathsBuf; NameIdx[0] != L
'\0'; NameIdx += Characters::CString::Length (NameIdx) + 1) {
278 if (not::FindNextVolume (hVol, volumeNameBuf,
static_cast<DWORD
> (std::size (volumeNameBuf)))) {
279 ::FindVolumeClose (hVol);
280 hVol = INVALID_HANDLE_VALUE;
285 DISABLE_COMPILER_MSC_WARNING_END (6262)
319#if qStroika_Foundation_Common_Platform_Linux
320 return ReadMountInfo_FromProcFSMounts_ ();
321#elif qStroika_Foundation_Common_Platform_MacOS
322 return ReadMountInfo_getfsent_ ();
323#elif qStroika_Foundation_Common_Platform_Windows
324 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)
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