2019-11-26 13:19:29 +00:00
|
|
|
#include "RemovableDriveManager.hpp"
|
|
|
|
#include <iostream>
|
2019-11-27 10:33:36 +00:00
|
|
|
#include "boost/nowide/convert.hpp"
|
2019-11-26 13:19:29 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
#if _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#include <tchar.h>
|
2019-11-27 10:33:36 +00:00
|
|
|
#include <winioctl.h>
|
2019-11-27 12:30:45 +00:00
|
|
|
#include <shlwapi.h>
|
2019-12-05 13:07:02 +00:00
|
|
|
|
2019-12-06 15:51:04 +00:00
|
|
|
#include <Dbt.h>
|
|
|
|
GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72,
|
|
|
|
0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
|
2019-12-05 13:07:02 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
#else
|
|
|
|
//linux includes
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <glob.h>
|
|
|
|
#include <libgen.h>
|
2019-11-28 15:35:22 +00:00
|
|
|
#include <pwd.h>
|
2019-11-26 14:52:18 +00:00
|
|
|
#endif
|
2019-11-26 13:19:29 +00:00
|
|
|
|
|
|
|
namespace Slic3r {
|
2019-12-03 09:09:53 +00:00
|
|
|
namespace GUI {
|
2019-11-28 12:50:58 +00:00
|
|
|
//std::vector<DriveData> RemovableDriveManager::m_current_drives;
|
|
|
|
//std::vector<std::function<void()>> RemovableDriveManager::m_callbacks;
|
2019-11-28 12:38:08 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
|
|
|
|
#if _WIN32
|
2019-12-06 15:51:04 +00:00
|
|
|
INT_PTR WINAPI WinProcCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
2019-11-27 10:33:36 +00:00
|
|
|
void RemovableDriveManager::search_for_drives()
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-11-27 10:33:36 +00:00
|
|
|
m_current_drives.clear();
|
|
|
|
m_current_drives.reserve(26);
|
2019-11-27 13:30:10 +00:00
|
|
|
DWORD drives_mask = GetLogicalDrives();
|
2019-11-26 13:19:29 +00:00
|
|
|
for (size_t i = 0; i < 26; i++)
|
|
|
|
{
|
2019-11-27 13:30:10 +00:00
|
|
|
if(drives_mask & (1 << i))
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
|
|
|
std::string path (1,(char)('A' + i));
|
|
|
|
path+=":";
|
2019-11-27 13:30:10 +00:00
|
|
|
UINT drive_type = GetDriveTypeA(path.c_str());
|
2019-11-26 13:19:29 +00:00
|
|
|
//std::cout << "found drive" << (char)('A' + i) << ": type:" <<driveType << "\n";
|
2019-11-27 13:30:10 +00:00
|
|
|
if (drive_type == DRIVE_REMOVABLE)
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
|
|
|
// get name of drive
|
|
|
|
std::wstring wpath = std::wstring(path.begin(), path.end());
|
2019-11-27 13:30:10 +00:00
|
|
|
std::wstring volume_name;
|
|
|
|
volume_name.resize(1024);
|
|
|
|
std::wstring file_system_name;
|
|
|
|
file_system_name.resize(1024);
|
|
|
|
LPWSTR lp_volume_name_buffer = new wchar_t;
|
|
|
|
BOOL error = GetVolumeInformationW(wpath.c_str(), &volume_name[0], sizeof(volume_name), NULL, NULL, NULL, &file_system_name[0], sizeof(file_system_name));
|
2019-11-26 13:19:29 +00:00
|
|
|
if(error != 0)
|
|
|
|
{
|
2019-11-27 13:30:10 +00:00
|
|
|
if (volume_name == L"")
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-11-27 13:30:10 +00:00
|
|
|
volume_name = L"REMOVABLE DRIVE";
|
2019-11-26 13:19:29 +00:00
|
|
|
}
|
2019-11-27 13:30:10 +00:00
|
|
|
if (file_system_name != L"")
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-11-27 13:30:10 +00:00
|
|
|
ULARGE_INTEGER free_space;
|
|
|
|
GetDiskFreeSpaceExA(path.c_str(), &free_space, NULL, NULL);
|
2019-11-26 13:19:29 +00:00
|
|
|
//std::cout << std::string(volumeName.begin(), volumeName.end()) << " " << std::string(fileSystemName.begin(), fileSystemName.end()) << " " << freeSpace.QuadPart << "\n";
|
2019-11-27 13:30:10 +00:00
|
|
|
if (free_space.QuadPart > 0)
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-12-03 09:55:38 +00:00
|
|
|
path += "\\";
|
2019-11-27 13:30:10 +00:00
|
|
|
m_current_drives.push_back(DriveData(boost::nowide::narrow(volume_name), path));
|
2019-11-26 13:19:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-28 12:38:08 +00:00
|
|
|
//std::cout << "found drives:" << m_current_drives.size() << "\n";
|
2019-11-26 13:19:29 +00:00
|
|
|
}
|
2019-11-27 10:33:36 +00:00
|
|
|
void RemovableDriveManager::eject_drive(const std::string &path)
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
|
|
|
|
2019-11-27 10:33:36 +00:00
|
|
|
//if (!update() || !is_drive_mounted(path))
|
|
|
|
if(m_current_drives.empty())
|
2019-11-26 13:19:29 +00:00
|
|
|
return;
|
2019-11-27 10:33:36 +00:00
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
|
|
|
if ((*it).path == path)
|
|
|
|
{
|
2019-11-27 10:33:36 +00:00
|
|
|
std::string mpath = "\\\\.\\" + path;
|
2019-12-03 09:55:38 +00:00
|
|
|
mpath = mpath.substr(0, mpath.size() - 1);
|
2019-12-05 13:07:02 +00:00
|
|
|
//std::cout << "Ejecting " << mpath << "\n";
|
2019-11-27 10:33:36 +00:00
|
|
|
HANDLE handle = CreateFileA(mpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
|
|
|
if (handle == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
std::cerr << "Ejecting " << mpath << " failed " << GetLastError() << " \n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DWORD deviceControlRetVal(0);
|
2019-12-11 16:02:12 +00:00
|
|
|
DeviceIoControl(handle, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
|
|
|
DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
2019-11-27 10:33:36 +00:00
|
|
|
BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &deviceControlRetVal, nullptr);
|
2019-11-27 13:30:10 +00:00
|
|
|
if (error == 0)
|
|
|
|
{
|
2019-12-11 16:02:12 +00:00
|
|
|
CloseHandle(handle);
|
2019-11-27 10:33:36 +00:00
|
|
|
std::cerr << "Ejecting " << mpath << " failed " << deviceControlRetVal << " " << GetLastError() << " \n";
|
2019-12-03 09:09:53 +00:00
|
|
|
return;
|
2019-11-27 13:30:10 +00:00
|
|
|
}
|
2019-12-11 16:02:12 +00:00
|
|
|
CloseHandle(handle);
|
2019-12-03 09:09:53 +00:00
|
|
|
|
2019-11-27 10:33:36 +00:00
|
|
|
m_current_drives.erase(it);
|
2019-11-26 13:19:29 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-27 13:30:10 +00:00
|
|
|
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
|
|
|
|
{
|
|
|
|
if (m_current_drives.empty())
|
|
|
|
return false;
|
|
|
|
int letter = PathGetDriveNumberA(path.c_str());
|
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
|
|
|
{
|
|
|
|
char drive = (*it).path[0];
|
|
|
|
if (drive == ('A' + letter))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-05 13:07:02 +00:00
|
|
|
std::string RemovableDriveManager::get_drive_from_path(const std::string& path)
|
|
|
|
{
|
|
|
|
int letter = PathGetDriveNumberA(path.c_str());
|
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
|
|
|
{
|
|
|
|
char drive = (*it).path[0];
|
|
|
|
if (drive == ('A' + letter))
|
|
|
|
return (*it).path;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2019-11-28 12:38:08 +00:00
|
|
|
void RemovableDriveManager::register_window()
|
|
|
|
{
|
2019-12-05 13:07:02 +00:00
|
|
|
std::cout << "Registering for device notification\n";
|
2019-11-28 12:38:08 +00:00
|
|
|
WNDCLASSEX wndClass;
|
|
|
|
wndClass.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
|
|
|
wndClass.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
|
|
|
|
wndClass.lpfnWndProc = reinterpret_cast<WNDPROC>(WinProcCallback);
|
|
|
|
wndClass.cbClsExtra = 0;
|
|
|
|
wndClass.cbWndExtra = 0;
|
|
|
|
wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
|
|
|
|
wndClass.hbrBackground = CreateSolidBrush(RGB(192, 192, 192));
|
|
|
|
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
|
2019-12-05 13:07:02 +00:00
|
|
|
wndClass.lpszClassName = L"PrusaSlicer_aux_class";
|
2019-11-28 12:38:08 +00:00
|
|
|
wndClass.lpszMenuName = NULL;
|
|
|
|
wndClass.hIconSm = wndClass.hIcon;
|
2019-12-06 15:51:04 +00:00
|
|
|
if(!RegisterClassEx(&wndClass))
|
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
|
|
|
return;
|
|
|
|
}
|
2019-12-05 13:07:02 +00:00
|
|
|
|
|
|
|
HWND hWnd = CreateWindowEx(
|
2019-12-06 15:51:04 +00:00
|
|
|
WS_EX_NOACTIVATE,
|
2019-12-05 13:07:02 +00:00
|
|
|
L"PrusaSlicer_aux_class",
|
|
|
|
L"PrusaSlicer_aux_wnd",
|
2019-12-06 15:51:04 +00:00
|
|
|
WS_DISABLED, // style
|
2019-12-05 13:07:02 +00:00
|
|
|
CW_USEDEFAULT, 0,
|
|
|
|
640, 480,
|
|
|
|
NULL, NULL,
|
2019-12-06 15:51:04 +00:00
|
|
|
GetModuleHandle(NULL),
|
2019-12-05 13:07:02 +00:00
|
|
|
NULL);
|
2019-12-06 15:51:04 +00:00
|
|
|
if(hWnd == NULL)
|
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
|
|
|
}
|
|
|
|
//ShowWindow(hWnd, SW_SHOWNORMAL);
|
|
|
|
UpdateWindow(hWnd);
|
2019-12-05 13:07:02 +00:00
|
|
|
}
|
2019-12-06 15:51:04 +00:00
|
|
|
|
2019-12-05 13:07:02 +00:00
|
|
|
INT_PTR WINAPI WinProcCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
LRESULT lRet = 1;
|
|
|
|
static HDEVNOTIFY hDeviceNotify;
|
2019-12-06 15:51:04 +00:00
|
|
|
|
2019-12-05 13:07:02 +00:00
|
|
|
static HWND hEditWnd;
|
|
|
|
static ULONGLONG msgCount = 0;
|
|
|
|
|
|
|
|
switch (message)
|
|
|
|
{
|
|
|
|
case WM_CREATE:
|
|
|
|
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
|
|
|
|
|
|
|
|
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
|
|
|
|
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
|
|
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
|
|
NotificationFilter.dbcc_classguid = WceusbshGUID;
|
|
|
|
|
|
|
|
hDeviceNotify = RegisterDeviceNotification(
|
|
|
|
hWnd, // events recipient
|
|
|
|
&NotificationFilter, // type of device
|
|
|
|
DEVICE_NOTIFY_WINDOW_HANDLE // type of recipient handle
|
|
|
|
);
|
|
|
|
break;
|
2019-12-11 16:02:12 +00:00
|
|
|
|
2019-12-05 13:07:02 +00:00
|
|
|
case WM_DEVICECHANGE:
|
|
|
|
{
|
2019-12-06 15:51:04 +00:00
|
|
|
if(wParam == DBT_DEVICEREMOVECOMPLETE)
|
2019-12-05 13:07:02 +00:00
|
|
|
{
|
2019-12-11 13:53:28 +00:00
|
|
|
- RemovableDriveManager::get_instance().update(0, true);
|
2019-12-05 13:07:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2019-12-11 16:02:12 +00:00
|
|
|
|
2019-12-05 13:07:02 +00:00
|
|
|
default:
|
|
|
|
// Send all other messages on to the default windows handler.
|
|
|
|
lRet = DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return lRet;
|
2019-11-28 12:38:08 +00:00
|
|
|
}
|
2019-12-06 15:51:04 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
#else
|
2019-11-27 10:33:36 +00:00
|
|
|
void RemovableDriveManager::search_for_drives()
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-12-10 10:35:39 +00:00
|
|
|
|
2019-12-09 14:33:10 +00:00
|
|
|
#if __APPLE__
|
2019-12-10 13:10:47 +00:00
|
|
|
if(m_rdmmm)
|
|
|
|
{
|
|
|
|
m_rdmmm->list_devices();
|
|
|
|
}
|
|
|
|
#else
|
2019-11-27 10:33:36 +00:00
|
|
|
m_current_drives.clear();
|
2019-11-27 13:30:10 +00:00
|
|
|
m_current_drives.reserve(26);
|
2019-11-26 14:52:18 +00:00
|
|
|
|
|
|
|
//search /media/* folder
|
2019-11-28 15:35:22 +00:00
|
|
|
search_path("/media/*", "/media");
|
2019-11-26 14:52:18 +00:00
|
|
|
|
2019-12-10 13:41:49 +00:00
|
|
|
/*
|
2019-12-04 09:05:18 +00:00
|
|
|
//search /Volumes/* folder (OSX)
|
|
|
|
search_path("/Volumes/*", "/Volumes");
|
2019-12-10 13:41:49 +00:00
|
|
|
*/
|
2019-11-28 15:35:22 +00:00
|
|
|
std::string path(std::getenv("USER"));
|
|
|
|
std::string pp(path);
|
|
|
|
//std::cout << "user: "<< path << "\n";
|
2019-12-04 10:47:47 +00:00
|
|
|
//if program is run with sudo, we have to search for all users
|
|
|
|
// but do we want that?
|
|
|
|
/*
|
|
|
|
if(path == "root"){
|
2019-11-28 15:35:22 +00:00
|
|
|
while (true) {
|
|
|
|
passwd* entry = getpwent();
|
|
|
|
if (!entry) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
path = entry->pw_name;
|
|
|
|
pp = path;
|
|
|
|
//search /media/USERNAME/* folder
|
|
|
|
pp = "/media/"+pp;
|
|
|
|
path = "/media/" + path + "/*";
|
|
|
|
search_path(path, pp);
|
2019-11-26 14:52:18 +00:00
|
|
|
|
2019-11-28 15:35:22 +00:00
|
|
|
//search /run/media/USERNAME/* folder
|
|
|
|
path = "/run" + path;
|
|
|
|
pp = "/run"+pp;
|
|
|
|
search_path(path, pp);
|
|
|
|
}
|
|
|
|
endpwent();
|
|
|
|
}else
|
2019-12-04 10:47:47 +00:00
|
|
|
*/
|
2019-11-28 15:35:22 +00:00
|
|
|
{
|
|
|
|
//search /media/USERNAME/* folder
|
|
|
|
pp = "/media/"+pp;
|
|
|
|
path = "/media/" + path + "/*";
|
|
|
|
search_path(path, pp);
|
2019-11-26 14:52:18 +00:00
|
|
|
|
2019-11-28 15:35:22 +00:00
|
|
|
//search /run/media/USERNAME/* folder
|
|
|
|
path = "/run" + path;
|
|
|
|
pp = "/run"+pp;
|
|
|
|
search_path(path, pp);
|
2019-11-26 14:52:18 +00:00
|
|
|
|
2019-11-28 15:35:22 +00:00
|
|
|
}
|
|
|
|
|
2019-12-04 14:27:33 +00:00
|
|
|
//std::cout << "found drives:" <<m_current_drives.size() << "\n";
|
2019-12-10 13:10:47 +00:00
|
|
|
#endif
|
2019-11-26 14:52:18 +00:00
|
|
|
}
|
2019-11-28 15:35:22 +00:00
|
|
|
void RemovableDriveManager::search_path(const std::string &path,const std::string &parent_path)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
|
|
|
glob_t globbuf;
|
|
|
|
globbuf.gl_offs = 2;
|
|
|
|
int error = glob(path.c_str(), GLOB_TILDE, NULL, &globbuf);
|
2019-11-28 15:35:22 +00:00
|
|
|
if(error == 0)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-11-27 13:30:10 +00:00
|
|
|
for(size_t i = 0; i < globbuf.gl_pathc; i++)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-12-10 13:41:49 +00:00
|
|
|
inspect_file(globbuf.gl_pathv[i], parent_path);
|
2019-11-26 14:52:18 +00:00
|
|
|
}
|
2019-11-28 15:35:22 +00:00
|
|
|
}else
|
|
|
|
{
|
|
|
|
//if error - path probably doesnt exists so function just exits
|
|
|
|
//std::cout<<"glob error "<< error<< "\n";
|
2019-11-26 14:52:18 +00:00
|
|
|
}
|
2019-11-27 13:30:10 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
globfree(&globbuf);
|
|
|
|
}
|
2019-12-10 13:10:47 +00:00
|
|
|
void RemovableDriveManager::inspect_file(const std::string &path, const std::string &parent_path)
|
|
|
|
{
|
|
|
|
//if not same file system - could be removable drive
|
2019-12-10 13:41:49 +00:00
|
|
|
if(!compare_filesystem_id(path, parent_path))
|
2019-12-10 13:10:47 +00:00
|
|
|
{
|
|
|
|
//user id
|
|
|
|
struct stat buf;
|
2019-12-10 13:41:49 +00:00
|
|
|
stat(path.c_str(), &buf);
|
2019-12-10 13:10:47 +00:00
|
|
|
uid_t uid = buf.st_uid;
|
|
|
|
std::string username(std::getenv("USER"));
|
|
|
|
struct passwd *pw = getpwuid(uid);
|
|
|
|
if(pw != 0)
|
|
|
|
{
|
|
|
|
if(pw->pw_name == username)
|
|
|
|
{
|
2019-12-10 13:41:49 +00:00
|
|
|
std::string name = basename(const_cast<char*>(path.c_str()));
|
|
|
|
m_current_drives.push_back(DriveData(name,path));
|
2019-12-10 13:10:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-28 15:35:22 +00:00
|
|
|
bool RemovableDriveManager::compare_filesystem_id(const std::string &path_a, const std::string &path_b)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
stat(path_a.c_str() ,&buf);
|
|
|
|
dev_t id_a = buf.st_dev;
|
|
|
|
stat(path_b.c_str() ,&buf);
|
|
|
|
dev_t id_b = buf.st_dev;
|
|
|
|
return id_a == id_b;
|
|
|
|
}
|
2019-11-27 10:33:36 +00:00
|
|
|
void RemovableDriveManager::eject_drive(const std::string &path)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-11-27 10:33:36 +00:00
|
|
|
if (m_current_drives.empty())
|
2019-11-26 14:52:18 +00:00
|
|
|
return;
|
|
|
|
|
2019-11-27 10:33:36 +00:00
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
|
|
|
if((*it).path == path)
|
|
|
|
{
|
2019-12-04 12:10:08 +00:00
|
|
|
|
|
|
|
std::string correct_path(path);
|
|
|
|
for (size_t i = 0; i < correct_path.size(); ++i)
|
|
|
|
{
|
|
|
|
if(correct_path[i]==' ')
|
|
|
|
{
|
2019-12-04 12:18:08 +00:00
|
|
|
correct_path = correct_path.insert(i,1,'\\');
|
2019-12-04 12:13:18 +00:00
|
|
|
i++;
|
2019-12-04 12:10:08 +00:00
|
|
|
}
|
|
|
|
}
|
2019-12-04 12:21:41 +00:00
|
|
|
std::cout<<"Ejecting "<<(*it).name<<" from "<< correct_path<<"\n";
|
2019-12-04 12:30:25 +00:00
|
|
|
|
|
|
|
std::string command = "";
|
|
|
|
#if __APPLE__
|
|
|
|
command = "diskutil unmount ";
|
|
|
|
#else
|
|
|
|
command = "umount ";
|
|
|
|
#endif
|
2019-12-04 12:18:08 +00:00
|
|
|
command += correct_path;
|
2019-12-03 09:09:53 +00:00
|
|
|
int err = system(command.c_str());
|
|
|
|
if(err)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-12-03 09:09:53 +00:00
|
|
|
std::cerr<<"Ejecting failed\n";
|
|
|
|
return;
|
2019-11-26 14:52:18 +00:00
|
|
|
}
|
2019-11-27 10:33:36 +00:00
|
|
|
m_current_drives.erase(it);
|
2019-12-03 09:09:53 +00:00
|
|
|
|
2019-11-26 14:52:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2019-11-27 13:30:10 +00:00
|
|
|
bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path)
|
|
|
|
{
|
|
|
|
if (m_current_drives.empty())
|
|
|
|
return false;
|
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
|
|
|
{
|
2019-11-28 15:35:22 +00:00
|
|
|
if(compare_filesystem_id(path, (*it).path))
|
2019-11-27 13:30:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-05 13:07:02 +00:00
|
|
|
std::string RemovableDriveManager::get_drive_from_path(const std::string& path)
|
|
|
|
{
|
|
|
|
//check if same filesystem
|
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
|
|
|
{
|
|
|
|
if (compare_filesystem_id(path, (*it).path))
|
|
|
|
return (*it).path;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2019-11-26 14:52:18 +00:00
|
|
|
#endif
|
2019-12-11 10:00:47 +00:00
|
|
|
|
|
|
|
RemovableDriveManager::RemovableDriveManager():
|
|
|
|
m_drives_count(0),
|
|
|
|
m_last_update(0),
|
2019-12-11 11:28:51 +00:00
|
|
|
m_last_save_path("")
|
2019-12-11 10:00:47 +00:00
|
|
|
#if __APPLE__
|
2019-12-11 11:28:51 +00:00
|
|
|
, m_rdmmm(new RDMMMWrapper())
|
2019-12-11 10:00:47 +00:00
|
|
|
#endif
|
|
|
|
{}
|
|
|
|
|
2019-12-06 15:51:04 +00:00
|
|
|
void RemovableDriveManager::init()
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-12-11 13:53:28 +00:00
|
|
|
//add_callback([](void) { RemovableDriveManager::get_instance().print(); });
|
2019-11-28 12:38:08 +00:00
|
|
|
#if _WIN32
|
2019-12-06 15:51:04 +00:00
|
|
|
register_window();
|
2019-12-10 10:17:12 +00:00
|
|
|
#elif __APPLE__
|
2019-12-11 10:00:47 +00:00
|
|
|
m_rdmmm->register_window();
|
2019-11-28 12:38:08 +00:00
|
|
|
#endif
|
2019-12-06 15:51:04 +00:00
|
|
|
update();
|
|
|
|
}
|
2019-12-11 11:28:51 +00:00
|
|
|
bool RemovableDriveManager::update(const long time, bool check)
|
2019-12-06 15:51:04 +00:00
|
|
|
{
|
2019-11-27 14:47:37 +00:00
|
|
|
if(time != 0) //time = 0 is forced update
|
|
|
|
{
|
2019-12-04 14:27:33 +00:00
|
|
|
long diff = m_last_update - time;
|
2019-11-27 14:47:37 +00:00
|
|
|
if(diff <= -2)
|
|
|
|
{
|
2019-12-04 14:27:33 +00:00
|
|
|
m_last_update = time;
|
2019-11-27 14:47:37 +00:00
|
|
|
}else
|
|
|
|
{
|
|
|
|
return false; // return value shouldnt matter if update didnt run
|
|
|
|
}
|
|
|
|
}
|
2019-12-11 15:59:26 +00:00
|
|
|
if(check)
|
|
|
|
{
|
|
|
|
m_rdmmm->log("update");
|
|
|
|
}
|
2019-11-27 10:33:36 +00:00
|
|
|
search_for_drives();
|
2019-12-11 11:28:51 +00:00
|
|
|
if(check)check_and_notify();
|
2019-11-27 10:33:36 +00:00
|
|
|
return !m_current_drives.empty();
|
2019-11-26 14:52:18 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 10:33:36 +00:00
|
|
|
|
|
|
|
bool RemovableDriveManager::is_drive_mounted(const std::string &path)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
2019-11-27 10:33:36 +00:00
|
|
|
for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it)
|
2019-11-26 14:52:18 +00:00
|
|
|
{
|
|
|
|
if ((*it).path == path)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2019-12-11 13:53:28 +00:00
|
|
|
std::string RemovableDriveManager::get_drive_path()
|
|
|
|
{
|
|
|
|
if (m_current_drives.size() == 0)
|
|
|
|
{
|
|
|
|
reset_last_save_path();
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
if (m_last_save_path != "")
|
|
|
|
return m_last_save_path;
|
|
|
|
return m_current_drives.back().path;
|
|
|
|
}
|
|
|
|
std::string RemovableDriveManager::get_last_save_path()
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-12-11 11:28:51 +00:00
|
|
|
return m_last_save_path;
|
2019-11-26 13:19:29 +00:00
|
|
|
}
|
2019-11-27 10:33:36 +00:00
|
|
|
std::vector<DriveData> RemovableDriveManager::get_all_drives()
|
2019-11-26 13:19:29 +00:00
|
|
|
{
|
2019-11-27 10:33:36 +00:00
|
|
|
return m_current_drives;
|
2019-11-26 13:19:29 +00:00
|
|
|
}
|
2019-11-28 12:38:08 +00:00
|
|
|
void RemovableDriveManager::check_and_notify()
|
|
|
|
{
|
2019-12-03 09:09:53 +00:00
|
|
|
//std::cout<<"drives count: "<<m_drives_count;
|
|
|
|
if(m_drives_count != m_current_drives.size())
|
2019-11-28 12:38:08 +00:00
|
|
|
{
|
2019-12-11 15:59:26 +00:00
|
|
|
m_rdmmm->log("drives count not same");
|
2019-12-03 09:09:53 +00:00
|
|
|
//std::cout<<" vs "<< m_current_drives.size();
|
2019-12-11 13:53:28 +00:00
|
|
|
if(m_callbacks.size() != 0 && m_drives_count > m_current_drives.size() && m_last_save_path != "" && !is_drive_mounted(m_last_save_path))
|
2019-11-28 12:38:08 +00:00
|
|
|
{
|
2019-12-05 13:07:02 +00:00
|
|
|
for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it)
|
|
|
|
{
|
|
|
|
(*it)();
|
|
|
|
}
|
2019-11-28 12:38:08 +00:00
|
|
|
}
|
2019-12-03 09:09:53 +00:00
|
|
|
m_drives_count = m_current_drives.size();
|
2019-11-28 12:38:08 +00:00
|
|
|
}
|
2019-12-03 09:09:53 +00:00
|
|
|
//std::cout<<"\n";
|
2019-11-28 12:38:08 +00:00
|
|
|
}
|
|
|
|
void RemovableDriveManager::add_callback(std::function<void()> callback)
|
|
|
|
{
|
|
|
|
m_callbacks.push_back(callback);
|
|
|
|
}
|
2019-12-06 12:21:44 +00:00
|
|
|
void RemovableDriveManager::erase_callbacks()
|
|
|
|
{
|
|
|
|
m_callbacks.clear();
|
|
|
|
}
|
2019-12-05 13:07:02 +00:00
|
|
|
void RemovableDriveManager::set_last_save_path(const std::string& path)
|
|
|
|
{
|
|
|
|
std::string last_drive = get_drive_from_path(path);
|
|
|
|
if(last_drive != "")
|
|
|
|
{
|
|
|
|
m_last_save_path = last_drive;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool RemovableDriveManager::is_last_drive_removed()
|
|
|
|
{
|
2019-12-11 13:53:28 +00:00
|
|
|
m_drives_count = m_current_drives.size();
|
2019-12-05 13:07:02 +00:00
|
|
|
if(m_last_save_path == "")
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2019-12-11 11:28:51 +00:00
|
|
|
bool r = !is_drive_mounted(m_last_save_path);
|
|
|
|
if (r) reset_last_save_path();
|
|
|
|
return r;
|
2019-12-05 13:07:02 +00:00
|
|
|
}
|
2019-12-05 15:22:54 +00:00
|
|
|
bool RemovableDriveManager::is_last_drive_removed_with_update(const long time)
|
|
|
|
{
|
2019-12-11 11:28:51 +00:00
|
|
|
update(time, false);
|
2019-12-05 15:22:54 +00:00
|
|
|
return is_last_drive_removed();
|
|
|
|
}
|
2019-12-05 13:07:02 +00:00
|
|
|
void RemovableDriveManager::reset_last_save_path()
|
|
|
|
{
|
|
|
|
m_last_save_path = "";
|
|
|
|
}
|
2019-12-09 14:33:10 +00:00
|
|
|
|
2019-11-28 12:38:08 +00:00
|
|
|
void RemovableDriveManager::print()
|
|
|
|
{
|
2019-12-05 15:22:54 +00:00
|
|
|
//std::cout << "Removed Device: "<<(int)is_last_drive_removed()<<"\n";
|
2019-11-28 12:38:08 +00:00
|
|
|
std::cout << "notified\n";
|
|
|
|
}
|
2019-12-10 10:17:12 +00:00
|
|
|
}}//namespace Slicer::Gui::
|