The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

446 lines
13KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. // (This file gets included by juce_linux_NativeCode.cpp, rather than being
  19. // compiled on its own).
  20. #ifdef JUCE_INCLUDED_FILE
  21. #define U_ISOFS_SUPER_MAGIC (short) 0x9660 // linux/iso_fs.h
  22. #define U_MSDOS_SUPER_MAGIC (short) 0x4d44 // linux/msdos_fs.h
  23. #define U_NFS_SUPER_MAGIC (short) 0x6969 // linux/nfs_fs.h
  24. #define U_SMB_SUPER_MAGIC (short) 0x517B // linux/smb_fs.h
  25. //==============================================================================
  26. void juce_getFileTimes (const String& fileName,
  27. int64& modificationTime,
  28. int64& accessTime,
  29. int64& creationTime) throw()
  30. {
  31. modificationTime = 0;
  32. accessTime = 0;
  33. creationTime = 0;
  34. struct stat info;
  35. const int res = stat (fileName.toUTF8(), &info);
  36. if (res == 0)
  37. {
  38. modificationTime = (int64) info.st_mtime * 1000;
  39. accessTime = (int64) info.st_atime * 1000;
  40. creationTime = (int64) info.st_ctime * 1000;
  41. }
  42. }
  43. bool juce_setFileTimes (const String& fileName,
  44. int64 modificationTime,
  45. int64 accessTime,
  46. int64 creationTime) throw()
  47. {
  48. struct utimbuf times;
  49. times.actime = (time_t) (accessTime / 1000);
  50. times.modtime = (time_t) (modificationTime / 1000);
  51. return utime (fileName.toUTF8(), &times) == 0;
  52. }
  53. bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw()
  54. {
  55. struct stat info;
  56. const int res = stat (fileName.toUTF8(), &info);
  57. if (res != 0)
  58. return false;
  59. info.st_mode &= 0777; // Just permissions
  60. if( isReadOnly )
  61. info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
  62. else
  63. // Give everybody write permission?
  64. info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
  65. return chmod (fileName.toUTF8(), info.st_mode) == 0;
  66. }
  67. bool juce_copyFile (const String& s, const String& d) throw()
  68. {
  69. const File source (s), dest (d);
  70. FileInputStream* in = source.createInputStream();
  71. bool ok = false;
  72. if (in != 0)
  73. {
  74. if (dest.deleteFile())
  75. {
  76. FileOutputStream* const out = dest.createOutputStream();
  77. if (out != 0)
  78. {
  79. const int bytesCopied = out->writeFromInputStream (*in, -1);
  80. delete out;
  81. ok = (bytesCopied == source.getSize());
  82. if (! ok)
  83. dest.deleteFile();
  84. }
  85. }
  86. delete in;
  87. }
  88. return ok;
  89. }
  90. const StringArray juce_getFileSystemRoots() throw()
  91. {
  92. StringArray s;
  93. s.add (T("/"));
  94. return s;
  95. }
  96. //==============================================================================
  97. bool File::isOnCDRomDrive() const throw()
  98. {
  99. struct statfs buf;
  100. if (statfs (getFullPathName().toUTF8(), &buf) == 0)
  101. return (buf.f_type == U_ISOFS_SUPER_MAGIC);
  102. // Assume not if this fails for some reason
  103. return false;
  104. }
  105. bool File::isOnHardDisk() const throw()
  106. {
  107. struct statfs buf;
  108. if (statfs (getFullPathName().toUTF8(), &buf) == 0)
  109. {
  110. switch (buf.f_type)
  111. {
  112. case U_ISOFS_SUPER_MAGIC: // CD-ROM
  113. case U_MSDOS_SUPER_MAGIC: // Probably floppy (but could be mounted FAT filesystem)
  114. case U_NFS_SUPER_MAGIC: // Network NFS
  115. case U_SMB_SUPER_MAGIC: // Network Samba
  116. return false;
  117. default:
  118. // Assume anything else is a hard-disk (but note it could
  119. // be a RAM disk. There isn't a good way of determining
  120. // this for sure)
  121. return true;
  122. }
  123. }
  124. // Assume so if this fails for some reason
  125. return true;
  126. }
  127. bool File::isOnRemovableDrive() const throw()
  128. {
  129. jassertfalse // xxx not implemented for linux!
  130. return false;
  131. }
  132. bool File::isHidden() const throw()
  133. {
  134. return getFileName().startsWithChar (T('.'));
  135. }
  136. //==============================================================================
  137. const File File::getSpecialLocation (const SpecialLocationType type)
  138. {
  139. switch (type)
  140. {
  141. case userHomeDirectory:
  142. {
  143. const char* homeDir = getenv ("HOME");
  144. if (homeDir == 0)
  145. {
  146. struct passwd* const pw = getpwuid (getuid());
  147. if (pw != 0)
  148. homeDir = pw->pw_dir;
  149. }
  150. return File (String::fromUTF8 ((const uint8*) homeDir));
  151. }
  152. case userDocumentsDirectory:
  153. case userMusicDirectory:
  154. case userMoviesDirectory:
  155. case userApplicationDataDirectory:
  156. return File ("~");
  157. case userDesktopDirectory:
  158. return File ("~/Desktop");
  159. case commonApplicationDataDirectory:
  160. return File ("/var");
  161. case globalApplicationsDirectory:
  162. return File ("/usr");
  163. case tempDirectory:
  164. {
  165. File tmp ("/var/tmp");
  166. if (! tmp.isDirectory())
  167. {
  168. tmp = T("/tmp");
  169. if (! tmp.isDirectory())
  170. tmp = File::getCurrentWorkingDirectory();
  171. }
  172. return tmp;
  173. }
  174. case currentExecutableFile:
  175. case currentApplicationFile:
  176. return juce_getExecutableFile();
  177. default:
  178. jassertfalse // unknown type?
  179. break;
  180. }
  181. return File::nonexistent;
  182. }
  183. //==============================================================================
  184. const File File::getCurrentWorkingDirectory() throw()
  185. {
  186. char buf [2048];
  187. return File (String::fromUTF8 ((const uint8*) getcwd (buf, sizeof (buf))));
  188. }
  189. bool File::setAsCurrentWorkingDirectory() const throw()
  190. {
  191. return chdir (getFullPathName().toUTF8()) == 0;
  192. }
  193. //==============================================================================
  194. const String File::getVersion() const throw()
  195. {
  196. return String::empty; // xxx not yet implemented
  197. }
  198. //==============================================================================
  199. const File File::getLinkedTarget() const throw()
  200. {
  201. char buffer [4096];
  202. size_t numChars = readlink ((const char*) getFullPathName().toUTF8(),
  203. buffer, sizeof (buffer));
  204. if (numChars > 0 && numChars <= sizeof (buffer))
  205. return File (String::fromUTF8 ((const uint8*) buffer, (int) numChars));
  206. return *this;
  207. }
  208. //==============================================================================
  209. bool File::moveToTrash() const throw()
  210. {
  211. if (! exists())
  212. return true;
  213. File trashCan (T("~/.Trash"));
  214. if (! trashCan.isDirectory())
  215. trashCan = T("~/.local/share/Trash/files");
  216. if (! trashCan.isDirectory())
  217. return false;
  218. return moveFileTo (trashCan.getNonexistentChildFile (getFileNameWithoutExtension(),
  219. getFileExtension()));
  220. }
  221. //==============================================================================
  222. struct FindFileStruct
  223. {
  224. String parentDir, wildCard;
  225. DIR* dir;
  226. bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize,
  227. Time* const modTime, Time* const creationTime, bool* const isReadOnly) throw()
  228. {
  229. const char* const wildcardUTF8 = wildCard.toUTF8();
  230. for (;;)
  231. {
  232. struct dirent* const de = readdir (dir);
  233. if (de == 0)
  234. break;
  235. if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
  236. {
  237. result = String::fromUTF8 ((const uint8*) de->d_name);
  238. const String path (parentDir + result);
  239. if (isDir != 0 || fileSize != 0)
  240. {
  241. struct stat info;
  242. const bool statOk = (stat (path.toUTF8(), &info) == 0);
  243. if (isDir != 0)
  244. *isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
  245. if (isHidden != 0)
  246. *isHidden = (de->d_name[0] == '.');
  247. if (fileSize != 0)
  248. *fileSize = statOk ? info.st_size : 0;
  249. }
  250. if (modTime != 0 || creationTime != 0)
  251. {
  252. int64 m, a, c;
  253. juce_getFileTimes (path, m, a, c);
  254. if (modTime != 0)
  255. *modTime = m;
  256. if (creationTime != 0)
  257. *creationTime = c;
  258. }
  259. if (isReadOnly != 0)
  260. *isReadOnly = ! juce_canWriteToFile (path);
  261. return true;
  262. }
  263. }
  264. return false;
  265. }
  266. };
  267. // returns 0 on failure
  268. void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
  269. bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
  270. Time* creationTime, bool* isReadOnly) throw()
  271. {
  272. DIR* d = opendir (directory.toUTF8());
  273. if (d != 0)
  274. {
  275. FindFileStruct* ff = new FindFileStruct();
  276. ff->parentDir = directory;
  277. if (!ff->parentDir.endsWithChar (File::separator))
  278. ff->parentDir += File::separator;
  279. ff->wildCard = wildCard;
  280. if (wildCard == T("*.*"))
  281. ff->wildCard = T("*");
  282. ff->dir = d;
  283. if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
  284. {
  285. return ff;
  286. }
  287. else
  288. {
  289. firstResultFile = String::empty;
  290. isDir = false;
  291. isHidden = false;
  292. closedir (d);
  293. delete ff;
  294. }
  295. }
  296. return 0;
  297. }
  298. bool juce_findFileNext (void* handle, String& resultFile,
  299. bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw()
  300. {
  301. FindFileStruct* const ff = (FindFileStruct*) handle;
  302. if (ff != 0)
  303. return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
  304. return false;
  305. }
  306. void juce_findFileClose (void* handle) throw()
  307. {
  308. FindFileStruct* const ff = (FindFileStruct*) handle;
  309. if (ff != 0)
  310. {
  311. closedir (ff->dir);
  312. delete ff;
  313. }
  314. }
  315. bool juce_launchFile (const String& fileName,
  316. const String& parameters) throw()
  317. {
  318. String cmdString (fileName);
  319. cmdString << " " << parameters;
  320. if (URL::isProbablyAWebsiteURL (fileName)
  321. || URL::isProbablyAnEmailAddress (fileName))
  322. {
  323. // create a command that tries to launch a bunch of likely browsers
  324. const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" };
  325. StringArray cmdLines;
  326. for (int i = 0; i < numElementsInArray (browserNames); ++i)
  327. cmdLines.add (String (browserNames[i]) + T(" ") + cmdString.trim().quoted());
  328. cmdString = cmdLines.joinIntoString (T(" || "));
  329. }
  330. if (cmdString.startsWithIgnoreCase (T("file:")))
  331. cmdString = cmdString.substring (5);
  332. const char* const argv[4] = { "/bin/sh", "-c", (const char*) cmdString.toUTF8(), 0 };
  333. const int cpid = fork();
  334. if (cpid == 0)
  335. {
  336. setsid();
  337. // Child process
  338. execve (argv[0], (char**) argv, environ);
  339. exit (0);
  340. }
  341. return cpid >= 0;
  342. }
  343. #endif