1 #include "QFatFs.h"
2
3 static QMap<QString,QFat*> cache;
4
~QFatFsHandler()5 QFatFsHandler::~QFatFsHandler()
6 {
7 QMapIterator<QString,QFat*> i(cache);
8 while (i.hasNext()) {
9 i.next();
10 i.value()->close();
11 delete i.value();
12 }
13 }
14
create(const QString & fileName) const15 QAbstractFileEngine * QFatFsHandler::create(const QString &fileName) const
16 {
17
18 QUrl u(fileName);
19 if (!u.isValid())
20 return NULL;
21 if (u.scheme() != "fat")
22 return NULL;
23
24 QString fatPath;
25 QString path = u.path();
26 if (!u.host().isEmpty())
27 fatPath = u.host() + u.path();
28 else {
29 fatPath = u.path();
30 }
31 if (fatPath.startsWith("/"))
32 fatPath.remove(0, 1);
33
34 QString name = u.fragment();
35
36 QMutexLocker locker(&mutex);
37 QFat* fat = cache[fatPath];
38 if(!fat) {
39 fat = new QFat(fatPath, m_clusterCount, m_clusterSize);
40 if(!fat) return 0;
41 if (fat->open() != FatNoError)
42 return 0;
43 cache[fatPath] = fat;
44 }
45 return new QFatEngine(fat,fatPath, name);
46 }
47
48 /*******************************/
49
FatIterator(QDir::Filters filters,const QStringList & nameFilters,QFat * fat,const QString & fatpath,const QString & name)50 FatIterator::FatIterator(QDir::Filters filters, const QStringList &nameFilters, QFat *fat, const QString& fatpath, const QString &name)
51 : QAbstractFileEngineIterator(filters,nameFilters)
52 , m_fat(fat)
53 , m_fatpath(fatpath)
54 , m_name(name)
55
56 {
57 m_curPath = m_name;
58 m_fat->getTocEntries(m_name, m_tocs);
59 m_curIndex = -1;
60 }
61
getNextIndex() const62 int FatIterator::getNextIndex() const
63 {
64 for (int i=m_curIndex+1; i<m_tocs.size(); ++i) {
65 if (filters() & QDir::AllEntries)
66 return i;
67 else if (filters() & QDir::Dirs) {
68 if (m_tocs[i].flags & FLAG_FOLDER)
69 return i;
70 } else if (filters() & QDir::Files) {
71 if (m_tocs[i].flags & FLAG_FILE)
72 return i;
73 }
74 }
75 return m_tocs.size();
76 }
77
hasNext() const78 bool FatIterator::hasNext() const
79 {
80 return (getNextIndex() < m_tocs.size());
81 }
82
next()83 QString FatIterator::next()
84 {
85 m_curIndex = getNextIndex();
86 QString path = "fat:///" + m_fatpath + "#" + m_name;
87 if(!path.endsWith("/")) path += "/";
88 return path + m_tocs[m_curIndex].name;
89 }
90
currentFileName() const91 QString FatIterator::currentFileName() const
92 {
93 return m_tocs[m_curIndex].name;
94 }
95
96 /**************************/
97
98 QMutex glob_mutex;
99
QFatEngine(QFat * fat,const QString & path,const QString & name)100 QFatEngine::QFatEngine(QFat* fat, const QString& path, const QString& name)
101 : m_fat(fat)
102 , m_fatpath(path)
103 , m_name(name)
104 , m_flags(0xffffffff)
105
106 {
107 m_flags &= (int)m_fat->m_fatFile->permissions();
108 if (m_name.isEmpty() || m_name == "/") {
109 m_flags |= RootFlag;
110 m_flags |= ExistsFlag;
111 m_flags |= DirectoryType;
112 } else {
113 QMutexLocker locker(&glob_mutex);
114 FatError ret = m_fat->getToc(m_name, m_toc);
115 if (ret == FatNoError && m_toc.flags) {
116 m_flags |= ExistsFlag;
117 if (m_toc.flags & FLAG_FILE)
118 m_flags |= FileType;
119 else if (m_toc.flags & FLAG_FOLDER) {
120 m_flags |= DirectoryType;
121 }
122 } else {
123 if(m_name.endsWith('/')) {
124 m_flags|= DirectoryType;
125 } else {
126 m_flags |= FileType;
127 }
128 }
129 }
130 }
131
open(QIODevice::OpenMode mode)132 bool QFatEngine::open( QIODevice::OpenMode mode)
133 {
134 QMutexLocker locker(&glob_mutex);
135
136 fatFile = new QFatFile(m_name, m_fat);
137 if (!fatFile->open(mode)) {
138 delete fatFile;
139 return false;
140 }
141 return true;
142 }
143
read(char * data,qint64 maxlen)144 qint64 QFatEngine::read( char * data, qint64 maxlen )
145 {
146 QMutexLocker locker(&glob_mutex);
147 return fatFile->read(data,maxlen);
148 }
149
readLine(char * data,qint64 maxlen)150 qint64 QFatEngine::readLine(char *data, qint64 maxlen)
151 {
152 QMutexLocker locker(&glob_mutex);
153 return fatFile->readLine(data,maxlen);
154 }
155
write(const char * data,qint64 len)156 qint64 QFatEngine::write(const char *data, qint64 len)
157 {
158 QMutexLocker locker(&glob_mutex);
159 return fatFile->write(data,len);
160 }
161
close()162 bool QFatEngine::close()
163 {
164 QMutexLocker locker(&glob_mutex);
165 fatFile->close();
166 delete fatFile;
167 return true;
168 }
169
beginEntryList(QDir::Filters filters,const QStringList & filterNames)170 QAbstractFileEngine::Iterator * QFatEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
171 {
172 QMutexLocker locker(&glob_mutex);
173 return new FatIterator(filters, filterNames, m_fat, m_fatpath, m_name);
174 }
175
fileTime(QAbstractFileEngine::FileTime time) const176 QDateTime QFatEngine::fileTime(QAbstractFileEngine::FileTime time) const
177 {
178 switch (time) {
179 case QAbstractFileEngine::CreationTime:
180 return QDateTime::fromTime_t(m_toc.creationTimestamp);
181 case QAbstractFileEngine::ModificationTime:
182 return QDateTime::fromTime_t(m_toc.modificationTimestamp);
183 default:
184 return QDateTime();
185 }
186 }
187
mkdir(const QString & dirName,bool createParentDirectories) const188 bool QFatEngine::mkdir(const QString &dirName, bool createParentDirectories) const
189 {
190 QUrl u(dirName);
191 if (!u.isValid() || u.scheme() != "fat")
192 return false;
193
194 bool ret;
195
196 QMutexLocker locker(&glob_mutex);
197
198 if (createParentDirectories)
199 ret = (m_fat->makeDirRecursive(u.fragment()) == FatNoError) ? true : false;
200 else
201 ret = (m_fat->makeDir(u.fragment()) == FatNoError) ? true : false;
202 m_fat->writeFat();
203
204 return ret;
205 }
206
rmdir(const QString & dirName,bool recurseParentDirectories) const207 bool QFatEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
208 {
209 QUrl u(dirName);
210 if (!u.isValid() || u.scheme() != "fat")
211 return false;
212
213 bool ret;
214
215 QMutexLocker locker(&glob_mutex);
216
217 if (recurseParentDirectories)
218 ret = (m_fat->removeDirRecursive(u.fragment()) == FatNoError) ? true : false;
219 else
220 ret = (m_fat->removeDir(u.fragment()) == FatNoError) ? true : false;
221 m_fat->writeFat();
222
223 return ret;
224 }
225
226
extension(QAbstractFileEngine::Extension extension,const QAbstractFileEngine::ExtensionOption * option,QAbstractFileEngine::ExtensionReturn * output)227 bool QFatEngine::extension(QAbstractFileEngine::Extension extension, const QAbstractFileEngine::ExtensionOption *option, QAbstractFileEngine::ExtensionReturn *output)
228 {
229 switch (extension) {
230 case QAbstractFileEngine::AtEndExtension:
231 return fatFile->atEnd();
232 default:
233 return false;
234 }
235 }
236
remove()237 bool QFatEngine::remove()
238 {
239 QMutexLocker locker(&glob_mutex);
240 if (m_fat->removeFile(m_name) != FatNoError)
241 return false;
242 m_fat->writeFat();
243
244 return true;
245 }
246
fileName(QAbstractFileEngine::FileName file) const247 QString QFatEngine::fileName(QAbstractFileEngine::FileName file) const
248 {
249 QStringList tokens;
250 tokens = m_name.split("/");
251 QString name = tokens.takeLast();
252 QString path = tokens.join("/");
253
254 switch (file) {
255 case QAbstractFileEngine::DefaultName:
256 case QAbstractFileEngine::AbsoluteName:
257 case QAbstractFileEngine::CanonicalName:
258 return "fat:///" + m_fatpath + "#" + m_name;
259 case QAbstractFileEngine::BaseName:
260 return name;
261 case QAbstractFileEngine::PathName:
262 case QAbstractFileEngine::AbsolutePathName:
263 case QAbstractFileEngine::CanonicalPathName:
264 return "fat:///" + m_fatpath + "#" + path;
265 }
266 }
267
flush()268 bool QFatEngine::flush()
269 {
270 return true;
271 }
272
seek(qint64 offset)273 bool QFatEngine::seek(qint64 offset)
274 {
275 return fatFile->seek(offset);
276 }
277
278
279