| @@ -352,6 +352,8 @@ bool File::isAbsolutePath (StringRef path) | |||
| File File::getChildFile (StringRef relativePath) const | |||
| { | |||
| jassert (! relativePath.isEmpty()); // passing in an empty filename? | |||
| if (isAbsolutePath (relativePath)) | |||
| return File (String (relativePath.text)); | |||
| @@ -353,8 +353,11 @@ public: | |||
| */ | |||
| bool isHidden() const; | |||
| /** If this file is a link, this returns the file that it points to. | |||
| If this file isn't actually link, it'll just return itself. | |||
| /** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */ | |||
| bool isLink() const; | |||
| /** If this file is a link or alias, this returns the file that it points to. | |||
| If the file isn't actually link, it'll just return itself. | |||
| */ | |||
| File getLinkedTarget() const; | |||
| @@ -198,6 +198,7 @@ namespace juce | |||
| //============================================================================== | |||
| #elif JUCE_LINUX | |||
| #include "native/juce_linux_CommonFile.cpp" | |||
| #include "native/juce_linux_Files.cpp" | |||
| #include "native/juce_linux_Network.cpp" | |||
| #include "native/juce_linux_SystemStats.cpp" | |||
| @@ -205,6 +206,7 @@ namespace juce | |||
| //============================================================================== | |||
| #elif JUCE_ANDROID | |||
| #include "native/juce_linux_CommonFile.cpp" | |||
| #include "native/juce_android_Files.cpp" | |||
| #include "native/juce_android_Misc.cpp" | |||
| #include "native/juce_android_Network.cpp" | |||
| @@ -26,34 +26,6 @@ | |||
| ============================================================================== | |||
| */ | |||
| bool File::copyInternal (const File& dest) const | |||
| { | |||
| FileInputStream in (*this); | |||
| if (dest.deleteFile()) | |||
| { | |||
| { | |||
| FileOutputStream out (dest); | |||
| if (out.failedToOpen()) | |||
| return false; | |||
| if (out.writeFromInputStream (in, -1) == getSize()) | |||
| return true; | |||
| } | |||
| dest.deleteFile(); | |||
| } | |||
| return false; | |||
| } | |||
| void File::findFileSystemRoots (Array<File>& destArray) | |||
| { | |||
| destArray.add (File ("/")); | |||
| } | |||
| //============================================================================== | |||
| bool File::isOnCDRomDrive() const | |||
| { | |||
| return false; | |||
| @@ -69,35 +41,11 @@ bool File::isOnRemovableDrive() const | |||
| return false; | |||
| } | |||
| bool File::isHidden() const | |||
| { | |||
| return getFileName().startsWithChar ('.'); | |||
| } | |||
| //============================================================================== | |||
| namespace | |||
| { | |||
| File juce_readlink (const String& file, const File& defaultFile) | |||
| { | |||
| const int size = 8192; | |||
| HeapBlock<char> buffer; | |||
| buffer.malloc (size + 4); | |||
| const size_t numBytes = readlink (file.toUTF8(), buffer, size); | |||
| if (numBytes > 0 && numBytes <= size) | |||
| return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes)); | |||
| return defaultFile; | |||
| } | |||
| } | |||
| File File::getLinkedTarget() const | |||
| String File::getVersion() const | |||
| { | |||
| return juce_readlink (getFullPathName().toUTF8(), *this); | |||
| return String::empty; | |||
| } | |||
| //============================================================================== | |||
| File File::getSpecialLocation (const SpecialLocationType type) | |||
| { | |||
| switch (type) | |||
| @@ -135,101 +83,15 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||
| return File::nonexistent; | |||
| } | |||
| //============================================================================== | |||
| String File::getVersion() const | |||
| { | |||
| return String::empty; | |||
| } | |||
| //============================================================================== | |||
| bool File::moveToTrash() const | |||
| { | |||
| if (! exists()) | |||
| return true; | |||
| // TODO | |||
| return false; | |||
| } | |||
| //============================================================================== | |||
| class DirectoryIterator::NativeIterator::Pimpl | |||
| { | |||
| public: | |||
| Pimpl (const File& directory, const String& wildCard_) | |||
| : parentDir (File::addTrailingSeparator (directory.getFullPathName())), | |||
| wildCard (wildCard_), | |||
| dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| } | |||
| ~Pimpl() | |||
| { | |||
| if (dir != 0) | |||
| closedir (dir); | |||
| } | |||
| bool next (String& filenameFound, | |||
| bool* const isDir, bool* const isHidden, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| if (dir != 0) | |||
| { | |||
| const char* wildcardUTF8 = nullptr; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| if (de == nullptr) | |||
| break; | |||
| if (wildcardUTF8 == nullptr) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly); | |||
| if (isHidden != 0) | |||
| *isHidden = filenameFound.startsWithChar ('.'); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| private: | |||
| String parentDir, wildCard; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl) | |||
| }; | |||
| DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard) | |||
| : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard)) | |||
| { | |||
| } | |||
| DirectoryIterator::NativeIterator::~NativeIterator() | |||
| { | |||
| } | |||
| bool DirectoryIterator::NativeIterator::next (String& filenameFound, | |||
| bool* const isDir, bool* const isHidden, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); | |||
| } | |||
| //============================================================================== | |||
| JUCE_API bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters) | |||
| { | |||
| const LocalRef<jstring> t (javaString (fileName)); | |||
| @@ -0,0 +1,153 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the juce_core module of the JUCE library. | |||
| Copyright (c) 2013 - Raw Material Software Ltd. | |||
| Permission to use, copy, modify, and/or distribute this software for any purpose with | |||
| or without fee is hereby granted, provided that the above copyright notice and this | |||
| permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||
| NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||
| DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||
| IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
| CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| ------------------------------------------------------------------------------ | |||
| NOTE! This permissive ISC license applies ONLY to files within the juce_core module! | |||
| All other JUCE modules are covered by a dual GPL/commercial license, so if you are | |||
| using any other modules, be sure to check that you also comply with their license. | |||
| For more details, visit www.juce.com | |||
| ============================================================================== | |||
| */ | |||
| bool File::copyInternal (const File& dest) const | |||
| { | |||
| FileInputStream in (*this); | |||
| if (dest.deleteFile()) | |||
| { | |||
| { | |||
| FileOutputStream out (dest); | |||
| if (out.failedToOpen()) | |||
| return false; | |||
| if (out.writeFromInputStream (in, -1) == getSize()) | |||
| return true; | |||
| } | |||
| dest.deleteFile(); | |||
| } | |||
| return false; | |||
| } | |||
| void File::findFileSystemRoots (Array<File>& destArray) | |||
| { | |||
| destArray.add (File ("/")); | |||
| } | |||
| bool File::isHidden() const | |||
| { | |||
| return getFileName().startsWithChar ('.'); | |||
| } | |||
| static String getLinkedFile (StringRef file) | |||
| { | |||
| HeapBlock<char> buffer (8194); | |||
| const int numBytes = (int) readlink (file.text, buffer, 8192); | |||
| return String::fromUTF8 (buffer, jmax (0, numBytes)); | |||
| }; | |||
| bool File::isLink() const | |||
| { | |||
| return getLinkedFile (getFullPathName()).isNotEmpty(); | |||
| } | |||
| File File::getLinkedTarget() const | |||
| { | |||
| String f (getLinkedFile (getFullPathName())); | |||
| if (f.isNotEmpty()) | |||
| return getSiblingFile (f); | |||
| return *this; | |||
| } | |||
| //============================================================================== | |||
| class DirectoryIterator::NativeIterator::Pimpl | |||
| { | |||
| public: | |||
| Pimpl (const File& directory, const String& wc) | |||
| : parentDir (File::addTrailingSeparator (directory.getFullPathName())), | |||
| wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| } | |||
| ~Pimpl() | |||
| { | |||
| if (dir != nullptr) | |||
| closedir (dir); | |||
| } | |||
| bool next (String& filenameFound, | |||
| bool* const isDir, bool* const isHidden, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| if (dir != nullptr) | |||
| { | |||
| const char* wildcardUTF8 = nullptr; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| if (de == nullptr) | |||
| break; | |||
| if (wildcardUTF8 == nullptr) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly); | |||
| if (isHidden != nullptr) | |||
| *isHidden = filenameFound.startsWithChar ('.'); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| private: | |||
| String parentDir, wildCard; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl) | |||
| }; | |||
| DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard) | |||
| : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard)) | |||
| { | |||
| } | |||
| DirectoryIterator::NativeIterator::~NativeIterator() {} | |||
| bool DirectoryIterator::NativeIterator::next (String& filenameFound, | |||
| bool* isDir, bool* isHidden, int64* fileSize, | |||
| Time* modTime, Time* creationTime, bool* isReadOnly) | |||
| { | |||
| return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); | |||
| } | |||
| @@ -34,35 +34,6 @@ enum | |||
| U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h | |||
| }; | |||
| //============================================================================== | |||
| bool File::copyInternal (const File& dest) const | |||
| { | |||
| FileInputStream in (*this); | |||
| if (dest.deleteFile()) | |||
| { | |||
| { | |||
| FileOutputStream out (dest); | |||
| if (out.failedToOpen()) | |||
| return false; | |||
| if (out.writeFromInputStream (in, -1) == getSize()) | |||
| return true; | |||
| } | |||
| dest.deleteFile(); | |||
| } | |||
| return false; | |||
| } | |||
| void File::findFileSystemRoots (Array<File>& destArray) | |||
| { | |||
| destArray.add (File ("/")); | |||
| } | |||
| //============================================================================== | |||
| bool File::isOnCDRomDrive() const | |||
| { | |||
| struct statfs buf; | |||
| @@ -85,11 +56,7 @@ bool File::isOnHardDisk() const | |||
| case U_SMB_SUPER_MAGIC: // Network Samba | |||
| return false; | |||
| default: | |||
| // Assume anything else is a hard-disk (but note it could | |||
| // be a RAM disk. There isn't a good way of determining | |||
| // this for sure) | |||
| return true; | |||
| default: break; | |||
| } | |||
| } | |||
| @@ -103,32 +70,9 @@ bool File::isOnRemovableDrive() const | |||
| return false; | |||
| } | |||
| bool File::isHidden() const | |||
| { | |||
| return getFileName().startsWithChar ('.'); | |||
| } | |||
| //============================================================================== | |||
| namespace | |||
| { | |||
| File juce_readlink (const String& file, const File& defaultFile) | |||
| { | |||
| const size_t size = 8192; | |||
| HeapBlock<char> buffer; | |||
| buffer.malloc (size + 4); | |||
| const size_t numBytes = readlink (file.toUTF8(), buffer, size); | |||
| if (numBytes > 0 && numBytes <= size) | |||
| return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes)); | |||
| return defaultFile; | |||
| } | |||
| } | |||
| File File::getLinkedTarget() const | |||
| String File::getVersion() const | |||
| { | |||
| return juce_readlink (getFullPathName().toUTF8(), *this); | |||
| return String::empty; // xxx not yet implemented | |||
| } | |||
| //============================================================================== | |||
| @@ -209,7 +153,10 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||
| return juce_getExecutableFile(); | |||
| case hostApplicationPath: | |||
| return juce_readlink ("/proc/self/exe", juce_getExecutableFile()); | |||
| { | |||
| const File f ("/proc/self/exe"); | |||
| return f.isLink() ? f.getLinkedTarget() : juce_getExecutableFile(); | |||
| } | |||
| default: | |||
| jassertfalse; // unknown type? | |||
| @@ -219,12 +166,6 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||
| return File::nonexistent; | |||
| } | |||
| //============================================================================== | |||
| String File::getVersion() const | |||
| { | |||
| return String::empty; // xxx not yet implemented | |||
| } | |||
| //============================================================================== | |||
| bool File::moveToTrash() const | |||
| { | |||
| @@ -243,81 +184,6 @@ bool File::moveToTrash() const | |||
| getFileExtension())); | |||
| } | |||
| //============================================================================== | |||
| class DirectoryIterator::NativeIterator::Pimpl | |||
| { | |||
| public: | |||
| Pimpl (const File& directory, const String& wc) | |||
| : parentDir (File::addTrailingSeparator (directory.getFullPathName())), | |||
| wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8())) | |||
| { | |||
| } | |||
| ~Pimpl() | |||
| { | |||
| if (dir != nullptr) | |||
| closedir (dir); | |||
| } | |||
| bool next (String& filenameFound, | |||
| bool* const isDir, bool* const isHidden, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| if (dir != nullptr) | |||
| { | |||
| const char* wildcardUTF8 = nullptr; | |||
| for (;;) | |||
| { | |||
| struct dirent* const de = readdir (dir); | |||
| if (de == nullptr) | |||
| break; | |||
| if (wildcardUTF8 == nullptr) | |||
| wildcardUTF8 = wildCard.toUTF8(); | |||
| if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0) | |||
| { | |||
| filenameFound = CharPointer_UTF8 (de->d_name); | |||
| updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly); | |||
| if (isHidden != nullptr) | |||
| *isHidden = filenameFound.startsWithChar ('.'); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| private: | |||
| String parentDir, wildCard; | |||
| DIR* dir; | |||
| JUCE_DECLARE_NON_COPYABLE (Pimpl) | |||
| }; | |||
| DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard) | |||
| : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard)) | |||
| { | |||
| } | |||
| DirectoryIterator::NativeIterator::~NativeIterator() | |||
| { | |||
| } | |||
| bool DirectoryIterator::NativeIterator::next (String& filenameFound, | |||
| bool* const isDir, bool* const isHidden, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly); | |||
| } | |||
| //============================================================================== | |||
| static bool isFileExecutable (const String& filename) | |||
| { | |||
| @@ -275,17 +275,25 @@ String File::getVersion() const | |||
| } | |||
| //============================================================================== | |||
| File File::getLinkedTarget() const | |||
| static NSString* getFileLink (const String& path) | |||
| { | |||
| #if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) | |||
| NSString* dest = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (getFullPathName()) error: nil]; | |||
| return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (path) error: nil]; | |||
| #else | |||
| // (the cast here avoids a deprecation warning) | |||
| NSString* dest = [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: juceStringToNS (getFullPathName())]; | |||
| return [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: juceStringToNS (path)]; | |||
| #endif | |||
| } | |||
| if (dest != nil) | |||
| return File (nsStringToJuce (dest)); | |||
| bool File::isLink() const | |||
| { | |||
| return getFileLink (fullPath) != nil; | |||
| } | |||
| File File::getLinkedTarget() const | |||
| { | |||
| if (NSString* dest = getFileLink (fullPath)) | |||
| return getSiblingFile (nsStringToJuce (dest)); | |||
| return *this; | |||
| } | |||
| @@ -590,6 +590,11 @@ String File::getVersion() const | |||
| } | |||
| //============================================================================== | |||
| bool File::isLink() const | |||
| { | |||
| return hasFileExtension (".lnk"); | |||
| } | |||
| File File::getLinkedTarget() const | |||
| { | |||
| File result (*this); | |||
| @@ -600,8 +605,8 @@ File File::getLinkedTarget() const | |||
| else if (! hasFileExtension (".lnk")) | |||
| return result; | |||
| ComSmartPtr <IShellLink> shellLink; | |||
| ComSmartPtr <IPersistFile> persistFile; | |||
| ComSmartPtr<IShellLink> shellLink; | |||
| ComSmartPtr<IPersistFile> persistFile; | |||
| if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink)) | |||
| && SUCCEEDED (shellLink.QueryInterface (persistFile)) | |||
| @@ -622,8 +627,8 @@ bool File::createLink (const String& description, const File& linkFileToCreate) | |||
| { | |||
| linkFileToCreate.deleteFile(); | |||
| ComSmartPtr <IShellLink> shellLink; | |||
| ComSmartPtr <IPersistFile> persistFile; | |||
| ComSmartPtr<IShellLink> shellLink; | |||
| ComSmartPtr<IPersistFile> persistFile; | |||
| return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink)) | |||
| && SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer())) | |||