1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
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.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
copyInternal(const File & dest) const26 bool File::copyInternal (const File& dest) const
27 {
28     FileInputStream in (*this);
29 
30     if (dest.deleteFile())
31     {
32         {
33             FileOutputStream out (dest);
34 
35             if (out.failedToOpen())
36                 return false;
37 
38             if (out.writeFromInputStream (in, -1) == getSize())
39                 return true;
40         }
41 
42         dest.deleteFile();
43     }
44 
45     return false;
46 }
47 
findFileSystemRoots(Array<File> & destArray)48 void File::findFileSystemRoots (Array<File>& destArray)
49 {
50     destArray.add (File ("/"));
51 }
52 
isHidden() const53 bool File::isHidden() const
54 {
55     return getFileName().startsWithChar ('.');
56 }
57 
isSymbolicLink() const58 bool File::isSymbolicLink() const
59 {
60     return getNativeLinkedTarget().isNotEmpty();
61 }
62 
getNativeLinkedTarget() const63 String File::getNativeLinkedTarget() const
64 {
65     HeapBlock<char> buffer (8194);
66     const int numBytes = (int) readlink (getFullPathName().toRawUTF8(), buffer, 8192);
67     return String::fromUTF8 (buffer, jmax (0, numBytes));
68 }
69 
70 //==============================================================================
71 class DirectoryIterator::NativeIterator::Pimpl
72 {
73 public:
Pimpl(const File & directory,const String & wc)74     Pimpl (const File& directory, const String& wc)
75         : parentDir (File::addTrailingSeparator (directory.getFullPathName())),
76           wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8()))
77     {
78     }
79 
~Pimpl()80     ~Pimpl()
81     {
82         if (dir != nullptr)
83             closedir (dir);
84     }
85 
next(String & filenameFound,bool * const isDir,bool * const isHidden,int64 * const fileSize,Time * const modTime,Time * const creationTime,bool * const isReadOnly)86     bool next (String& filenameFound,
87                bool* const isDir, bool* const isHidden, int64* const fileSize,
88                Time* const modTime, Time* const creationTime, bool* const isReadOnly)
89     {
90         if (dir != nullptr)
91         {
92             const char* wildcardUTF8 = nullptr;
93 
94             for (;;)
95             {
96                 struct dirent* const de = readdir (dir);
97 
98                 if (de == nullptr)
99                     break;
100 
101                 if (wildcardUTF8 == nullptr)
102                     wildcardUTF8 = wildCard.toUTF8();
103 
104                 if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
105                 {
106                     filenameFound = CharPointer_UTF8 (de->d_name);
107 
108                     updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
109 
110                     if (isHidden != nullptr)
111                         *isHidden = filenameFound.startsWithChar ('.');
112 
113                     return true;
114                 }
115             }
116         }
117 
118         return false;
119     }
120 
121 private:
122     String parentDir, wildCard;
123     DIR* dir;
124 
125     JUCE_DECLARE_NON_COPYABLE (Pimpl)
126 };
127 
NativeIterator(const File & directory,const String & wildCardStr)128 DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCardStr)
129     : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCardStr))
130 {
131 }
132 
~NativeIterator()133 DirectoryIterator::NativeIterator::~NativeIterator() {}
134 
next(String & filenameFound,bool * isDir,bool * isHidden,int64 * fileSize,Time * modTime,Time * creationTime,bool * isReadOnly)135 bool DirectoryIterator::NativeIterator::next (String& filenameFound,
136                                               bool* isDir, bool* isHidden, int64* fileSize,
137                                               Time* modTime, Time* creationTime, bool* isReadOnly)
138 {
139     return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
140 }
141 
142 } // namespace juce
143