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.

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