You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
5.1KB

  1. #include "system.hpp"
  2. #include "string.hpp"
  3. #include <thread>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #if defined ARCH_LIN || defined ARCH_MAC
  7. #include <pthread.h>
  8. #include <sched.h>
  9. #include <execinfo.h> // for backtrace and backtrace_symbols
  10. #include <unistd.h> // for execl
  11. #include <sys/utsname.h>
  12. #endif
  13. #if defined ARCH_WIN
  14. #include <windows.h>
  15. #include <shellapi.h>
  16. #include <processthreadsapi.h>
  17. #include <dbghelp.h>
  18. #endif
  19. namespace rack {
  20. namespace system {
  21. std::list<std::string> listEntries(const std::string &path) {
  22. std::list<std::string> filenames;
  23. DIR *dir = opendir(path.c_str());
  24. if (dir) {
  25. struct dirent *d;
  26. while ((d = readdir(dir))) {
  27. std::string filename = d->d_name;
  28. if (filename == "." || filename == "..")
  29. continue;
  30. filenames.push_back(path + "/" + filename);
  31. }
  32. closedir(dir);
  33. }
  34. filenames.sort();
  35. return filenames;
  36. }
  37. bool isFile(const std::string &path) {
  38. struct stat statbuf;
  39. if (stat(path.c_str(), &statbuf))
  40. return false;
  41. return S_ISREG(statbuf.st_mode);
  42. }
  43. bool isDirectory(const std::string &path) {
  44. struct stat statbuf;
  45. if (stat(path.c_str(), &statbuf))
  46. return false;
  47. return S_ISDIR(statbuf.st_mode);
  48. }
  49. void copyFile(const std::string &srcPath, const std::string &destPath) {
  50. // Open files
  51. FILE *source = fopen(srcPath.c_str(), "rb");
  52. if (!source)
  53. return;
  54. DEFER({
  55. fclose(source);
  56. });
  57. FILE *dest = fopen(destPath.c_str(), "wb");
  58. if (!dest)
  59. return;
  60. DEFER({
  61. fclose(dest);
  62. });
  63. // Copy buffer
  64. const int bufferSize = (1<<15);
  65. char buffer[bufferSize];
  66. while (1) {
  67. size_t size = fread(buffer, 1, bufferSize, source);
  68. if (size == 0)
  69. break;
  70. size = fwrite(buffer, 1, size, dest);
  71. if (size == 0)
  72. break;
  73. }
  74. }
  75. void createDirectory(const std::string &path) {
  76. #if defined ARCH_WIN
  77. std::wstring pathW = string::toWstring(path);
  78. CreateDirectoryW(pathW.c_str(), NULL);
  79. #else
  80. mkdir(path.c_str(), 0755);
  81. #endif
  82. }
  83. int getLogicalCoreCount() {
  84. // TODO Return the physical cores, not logical cores.
  85. return std::thread::hardware_concurrency();
  86. }
  87. void setThreadName(const std::string &name) {
  88. #if defined ARCH_LIN
  89. pthread_setname_np(pthread_self(), name.c_str());
  90. #elif defined ARCH_WIN
  91. // Unsupported on Windows
  92. #endif
  93. }
  94. void setThreadRealTime() {
  95. #if defined ARCH_LIN || defined ARCH_MAC
  96. // Round-robin scheduler policy
  97. int policy = SCHED_RR;
  98. struct sched_param param;
  99. param.sched_priority = sched_get_priority_max(policy);
  100. pthread_setschedparam(pthread_self(), policy, &param);
  101. #elif defined ARCH_WIN
  102. // Set process class first
  103. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  104. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  105. #endif
  106. }
  107. std::string getStackTrace() {
  108. int stackLen = 128;
  109. void *stack[stackLen];
  110. std::string s;
  111. #if defined ARCH_LIN || defined ARCH_MAC
  112. stackLen = backtrace(stack, stackLen);
  113. char **strings = backtrace_symbols(stack, stackLen);
  114. for (int i = 1; i < stackLen; i++) {
  115. s += string::f("%d: %s\n", stackLen - i - 1, strings[i]);
  116. }
  117. free(strings);
  118. #elif defined ARCH_WIN
  119. HANDLE process = GetCurrentProcess();
  120. SymInitialize(process, NULL, true);
  121. stackLen = CaptureStackBackTrace(0, stackLen, stack, NULL);
  122. SYMBOL_INFO *symbol = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256, 1);
  123. symbol->MaxNameLen = 255;
  124. symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
  125. for (int i = 1; i < stackLen; i++) {
  126. SymFromAddr(process, (DWORD64) stack[i], 0, symbol);
  127. s += string::f("%d: %s 0x%0x\n", stackLen - i - 1, symbol->Name, symbol->Address);
  128. }
  129. free(symbol);
  130. #endif
  131. return s;
  132. }
  133. void openBrowser(const std::string &url) {
  134. #if defined ARCH_LIN
  135. std::string command = "xdg-open \"" + url + "\"";
  136. (void) std::system(command.c_str());
  137. #endif
  138. #if defined ARCH_MAC
  139. std::string command = "open \"" + url + "\"";
  140. std::system(command.c_str());
  141. #endif
  142. #if defined ARCH_WIN
  143. std::wstring urlW = string::toWstring(url);
  144. ShellExecuteW(NULL, L"open", urlW.c_str(), NULL, NULL, SW_SHOWNORMAL);
  145. #endif
  146. }
  147. void openFolder(const std::string &path) {
  148. #if defined ARCH_LIN
  149. std::string command = "xdg-open \"" + path + "\"";
  150. (void) std::system(command.c_str());
  151. #endif
  152. #if defined ARCH_WIN
  153. std::wstring pathW = string::toWstring(path);
  154. ShellExecuteW(NULL, L"explorer", pathW.c_str(), NULL, NULL, SW_SHOWNORMAL);
  155. #endif
  156. }
  157. void runProcessAsync(const std::string &path) {
  158. #if defined ARCH_WIN
  159. STARTUPINFOW startupInfo;
  160. PROCESS_INFORMATION processInfo;
  161. std::memset(&startupInfo, 0, sizeof(startupInfo));
  162. startupInfo.cb = sizeof(startupInfo);
  163. std::memset(&processInfo, 0, sizeof(processInfo));
  164. std::wstring pathW = string::toWstring(path);
  165. CreateProcessW(pathW.c_str(), NULL,
  166. NULL, NULL, false, 0, NULL, NULL,
  167. &startupInfo, &processInfo);
  168. #endif
  169. }
  170. std::string getOperatingSystemInfo() {
  171. #if defined ARCH_LIN || defined ARCH_MAC
  172. struct utsname u;
  173. uname(&u);
  174. return string::f("%s %s %s %s", u.sysname, u.release, u.version, u.machine);
  175. #elif defined ARCH_WIN
  176. OSVERSIONINFOW info;
  177. ZeroMemory(&info, sizeof(info));
  178. info.dwOSVersionInfoSize = sizeof(info);
  179. GetVersionExW(&info);
  180. return string::f("Windows %u.%u", info.dwMajorVersion, info.dwMinorVersion);
  181. #endif
  182. }
  183. } // namespace system
  184. } // namespace rack