2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
20 ==============================================================================
24 extern char** environ
;
32 U_ISOFS_SUPER_MAGIC
= 0x9660, // linux/iso_fs.h
33 U_MSDOS_SUPER_MAGIC
= 0x4d44, // linux/msdos_fs.h
34 U_NFS_SUPER_MAGIC
= 0x6969, // linux/nfs_fs.h
35 U_SMB_SUPER_MAGIC
= 0x517B // linux/smb_fs.h
38 bool File::isOnCDRomDrive() const
42 return statfs (getFullPathName().toUTF8(), &buf
) == 0
43 && buf
.f_type
== (unsigned int) U_ISOFS_SUPER_MAGIC
;
46 bool File::isOnHardDisk() const
50 if (statfs (getFullPathName().toUTF8(), &buf
) == 0)
54 case U_ISOFS_SUPER_MAGIC
: // CD-ROM
55 case U_MSDOS_SUPER_MAGIC
: // Probably floppy (but could be mounted FAT filesystem)
56 case U_NFS_SUPER_MAGIC
: // Network NFS
57 case U_SMB_SUPER_MAGIC
: // Network Samba
64 // Assume so if this fails for some reason
68 bool File::isOnRemovableDrive() const
70 jassertfalse
; // xxx not implemented for linux!
74 String
File::getVersion() const
76 return {}; // xxx not yet implemented
79 //==============================================================================
80 static File
resolveXDGFolder (const char* const type
, const char* const fallbackFolder
)
82 StringArray confLines
;
83 File ("~/.config/user-dirs.dirs").readLines (confLines
);
85 for (int i
= 0; i
< confLines
.size(); ++i
)
87 const String
line (confLines
[i
].trimStart());
89 if (line
.startsWith (type
))
91 // eg. resolve XDG_MUSIC_DIR="$HOME/Music" to /home/user/Music
92 const File
f (line
.replace ("$HOME", File ("~").getFullPathName())
93 .fromFirstOccurrenceOf ("=", false, false)
101 return File (fallbackFolder
);
104 const char* const* juce_argv
= nullptr;
107 File
File::getSpecialLocation (const SpecialLocationType type
)
111 case userHomeDirectory
:
113 if (const char* homeDir
= getenv ("HOME"))
114 return File (CharPointer_UTF8 (homeDir
));
116 if (auto* pw
= getpwuid (getuid()))
117 return File (CharPointer_UTF8 (pw
->pw_dir
));
122 case userDocumentsDirectory
: return resolveXDGFolder ("XDG_DOCUMENTS_DIR", "~/Documents");
123 case userMusicDirectory
: return resolveXDGFolder ("XDG_MUSIC_DIR", "~/Music");
124 case userMoviesDirectory
: return resolveXDGFolder ("XDG_VIDEOS_DIR", "~/Videos");
125 case userPicturesDirectory
: return resolveXDGFolder ("XDG_PICTURES_DIR", "~/Pictures");
126 case userDesktopDirectory
: return resolveXDGFolder ("XDG_DESKTOP_DIR", "~/Desktop");
127 case userApplicationDataDirectory
: return resolveXDGFolder ("XDG_CONFIG_HOME", "~/.config");
128 case commonDocumentsDirectory
:
129 case commonApplicationDataDirectory
: return File ("/opt");
130 case globalApplicationsDirectory
: return File ("/usr");
134 if (const char* tmpDir
= getenv ("TMPDIR"))
135 return File (CharPointer_UTF8 (tmpDir
));
137 return File ("/tmp");
140 case invokedExecutableFile
:
141 if (juce_argv
!= nullptr && juce_argc
> 0)
142 return File (String (CharPointer_UTF8 (juce_argv
[0])));
146 case currentExecutableFile
:
147 case currentApplicationFile
:
148 #if ! JUCE_STANDALONE_APPLICATION
149 return juce_getExecutableFile();
151 // deliberate fall-through if this is not a shared-library
154 case hostApplicationPath
:
157 return juce_getExecutableFile();
159 const File
f ("/proc/self/exe");
160 return f
.isSymbolicLink() ? f
.getLinkedTarget() : juce_getExecutableFile();
165 jassertfalse
; // unknown type?
172 //==============================================================================
173 bool File::moveToTrash() const
178 File
trashCan ("~/.Trash");
180 if (! trashCan
.isDirectory())
181 trashCan
= "~/.local/share/Trash/files";
183 if (! trashCan
.isDirectory())
186 return moveFileTo (trashCan
.getNonexistentChildFile (getFileNameWithoutExtension(),
187 getFileExtension()));
190 //==============================================================================
191 static bool isFileExecutable (const String
& filename
)
193 juce_statStruct info
;
195 return juce_stat (filename
, info
)
196 && S_ISREG (info
.st_mode
)
197 && access (filename
.toUTF8(), X_OK
) == 0;
200 bool Process::openDocument (const String
& fileName
, const String
& parameters
)
202 const auto cmdString
= [&]
204 if (fileName
.startsWithIgnoreCase ("file:")
205 || File::createFileWithoutCheckingPath (fileName
).isDirectory()
206 || ! isFileExecutable (fileName
))
208 const auto singleCommand
= fileName
.trim().quoted();
210 StringArray cmdLines
;
212 for (auto browserName
: { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
213 "google-chrome", "chromium-browser", "opera", "konqueror" })
215 cmdLines
.add (String (browserName
) + " " + singleCommand
);
218 return cmdLines
.joinIntoString (" || ");
221 return (fileName
.replace (" ", "\\ ", false) + " " + parameters
).trim();
224 const char* const argv
[] = { "/bin/sh", "-c", cmdString
.toUTF8(), nullptr };
227 const auto cpid
= vfork();
229 const auto cpid
= fork();
239 if (execve (argv
[0], (char**) argv
, environ
) < 0)
246 void File::revealToUser() const
250 else if (getParentDirectory().exists())
251 getParentDirectory().startAsProcess();