GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* The ManaPlus Client |
||
3 |
* Copyright (C) 2013-2019 The ManaPlus Developers |
||
4 |
* Copyright (C) 2019-2021 Andrei Karas |
||
5 |
* |
||
6 |
* This file is part of The ManaPlus Client. |
||
7 |
* |
||
8 |
* This program is free software; you can redistribute it and/or modify |
||
9 |
* it under the terms of the GNU General Public License as published by |
||
10 |
* the Free Software Foundation; either version 2 of the License, or |
||
11 |
* any later version. |
||
12 |
* |
||
13 |
* This program is distributed in the hope that it will be useful, |
||
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 |
* GNU General Public License for more details. |
||
17 |
* |
||
18 |
* You should have received a copy of the GNU General Public License |
||
19 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
20 |
*/ |
||
21 |
|||
22 |
#include "fs/virtfs/fsdir.h" |
||
23 |
|||
24 |
#include "fs/files.h" |
||
25 |
#include "fs/mkdir.h" |
||
26 |
#include "fs/paths.h" |
||
27 |
|||
28 |
#include "fs/virtfs/direntry.h" |
||
29 |
#include "fs/virtfs/file.h" |
||
30 |
#include "fs/virtfs/fsdirrwops.h" |
||
31 |
#include "fs/virtfs/fsfuncs.h" |
||
32 |
#include "fs/virtfs/list.h" |
||
33 |
|||
34 |
#include "utils/cast.h" |
||
35 |
#include "utils/checkutils.h" |
||
36 |
#include "utils/foreach.h" |
||
37 |
#include "utils/stdmove.h" |
||
38 |
#include "utils/stringutils.h" |
||
39 |
|||
40 |
#include <dirent.h> |
||
41 |
#include <unistd.h> |
||
42 |
|||
43 |
#include <sys/types.h> |
||
44 |
#include <sys/stat.h> |
||
45 |
|||
46 |
#include "debug.h" |
||
47 |
|||
48 |
extern const char *dirSeparator; |
||
49 |
|||
50 |
namespace VirtFs |
||
51 |
{ |
||
52 |
|||
53 |
namespace |
||
54 |
{ |
||
55 |
1 |
std::string mWriteDir; |
|
56 |
1 |
std::string mBaseDir; |
|
57 |
1 |
std::string mUserDir; |
|
58 |
bool mPermitLinks = false; |
||
59 |
FsFuncs funcs; |
||
60 |
} // namespace |
||
61 |
|||
62 |
namespace FsDir |
||
63 |
{ |
||
64 |
3984 |
File *openInternal(FsEntry *restrict const entry, |
|
65 |
const std::string &filename, |
||
66 |
const FILEMTYPE mode) |
||
67 |
{ |
||
68 |
const std::string path = static_cast<DirEntry*>(entry)->rootSubDir + |
||
69 |
7968 |
filename; |
|
70 |
✓✗✓✓ |
3984 |
if (Files::existsLocal(path) == false) |
71 |
return nullptr; |
||
72 |
✓✗ | 2337 |
FILEHTYPE fd = FILEOPEN(path.c_str(), |
73 |
mode); |
||
74 |
✗✓ | 2337 |
if (fd == FILEHDEFAULT) |
75 |
{ |
||
76 |
reportAlways("VirtFs::open file open error: %s", |
||
77 |
filename.c_str()) |
||
78 |
return nullptr; |
||
79 |
} |
||
80 |
✓✗✓✗ |
2337 |
return new File(&funcs, fd); |
81 |
} |
||
82 |
|||
83 |
3984 |
File *openRead(FsEntry *restrict const entry, |
|
84 |
std::string filename) |
||
85 |
{ |
||
86 |
3984 |
return openInternal(entry, filename, FILEOPEN_FLAG_READ); |
|
87 |
} |
||
88 |
|||
89 |
File *openWrite(FsEntry *restrict const entry, |
||
90 |
const std::string &filename) |
||
91 |
{ |
||
92 |
return openInternal(entry, filename, FILEOPEN_FLAG_WRITE); |
||
93 |
} |
||
94 |
|||
95 |
File *openAppend(FsEntry *restrict const entry, |
||
96 |
const std::string &filename) |
||
97 |
{ |
||
98 |
return openInternal(entry, filename, FILEOPEN_FLAG_APPEND); |
||
99 |
} |
||
100 |
|||
101 |
119 |
void deinit() |
|
102 |
{ |
||
103 |
119 |
} |
|
104 |
|||
105 |
#if defined(__native_client__) |
||
106 |
void init(const std::string &restrict name A_UNUSED) |
||
107 |
{ |
||
108 |
mBaseDir = "/"; |
||
109 |
#elif defined(ANDROID) |
||
110 |
void init(const std::string &restrict name A_UNUSED) |
||
111 |
{ |
||
112 |
mBaseDir = getRealPath("."); |
||
113 |
#else // defined(__native_client__) |
||
114 |
|||
115 |
120 |
void init(const std::string &restrict name) |
|
116 |
{ |
||
117 |
✓✗ | 360 |
mBaseDir = getRealPath(getFileDir(name)); |
118 |
#endif // defined(__native_client__) |
||
119 |
|||
120 |
120 |
prepareFsPath(mBaseDir); |
|
121 |
240 |
mUserDir = getHomePath(); |
|
122 |
120 |
prepareFsPath(mUserDir); |
|
123 |
120 |
initFuncs(&funcs); |
|
124 |
120 |
} |
|
125 |
|||
126 |
void initFuncs(FsFuncs *restrict const ptr) |
||
127 |
{ |
||
128 |
120 |
ptr->close = &FsDir::close; |
|
129 |
120 |
ptr->read = &FsDir::read; |
|
130 |
120 |
ptr->write = &FsDir::write; |
|
131 |
120 |
ptr->fileLength = &FsDir::fileLength; |
|
132 |
120 |
ptr->tell = &FsDir::tell; |
|
133 |
120 |
ptr->seek = &FsDir::seek; |
|
134 |
120 |
ptr->eof = &FsDir::eof; |
|
135 |
120 |
ptr->exists = &FsDir::exists; |
|
136 |
120 |
ptr->getRealDir = &FsDir::getRealDir; |
|
137 |
120 |
ptr->enumerate = &FsDir::enumerate; |
|
138 |
120 |
ptr->isDirectory = &FsDir::isDirectory; |
|
139 |
120 |
ptr->openRead = &FsDir::openRead; |
|
140 |
120 |
ptr->openWrite = &FsDir::openWrite; |
|
141 |
120 |
ptr->openAppend = &FsDir::openAppend; |
|
142 |
120 |
ptr->loadFile = &FsDir::loadFile; |
|
143 |
120 |
ptr->getFiles = &FsDir::getFiles; |
|
144 |
120 |
ptr->getFilesWithDir = &FsDir::getFilesWithDir; |
|
145 |
120 |
ptr->getDirs = &FsDir::getDirs; |
|
146 |
120 |
ptr->rwops_seek = &FsDir::rwops_seek; |
|
147 |
120 |
ptr->rwops_read = &FsDir::rwops_read; |
|
148 |
120 |
ptr->rwops_write = &FsDir::rwops_write; |
|
149 |
120 |
ptr->rwops_close = &FsDir::rwops_close; |
|
150 |
#ifdef USE_SDL2 |
||
151 |
120 |
ptr->rwops_size = &FsDir::rwops_size; |
|
152 |
#endif // USE_SDL2 |
||
153 |
} |
||
154 |
|||
155 |
510 |
FsFuncs *getFuncs() |
|
156 |
{ |
||
157 |
510 |
return &funcs; |
|
158 |
} |
||
159 |
|||
160 |
293 |
const char *getBaseDir() |
|
161 |
{ |
||
162 |
293 |
return mBaseDir.c_str(); |
|
163 |
} |
||
164 |
|||
165 |
583 |
const char *getUserDir() |
|
166 |
{ |
||
167 |
583 |
return mUserDir.c_str(); |
|
168 |
} |
||
169 |
|||
170 |
69 |
bool getRealDir(FsEntry *restrict const entry, |
|
171 |
std::string filename, |
||
172 |
std::string dirName A_UNUSED, |
||
173 |
std::string &realDir) |
||
174 |
{ |
||
175 |
69 |
const DirEntry *const dirEntry = static_cast<const DirEntry*>(entry); |
|
176 |
✓✗✓✓ |
138 |
if (Files::existsLocal(dirEntry->rootSubDir + filename)) |
177 |
{ |
||
178 |
70 |
realDir = dirEntry->userDir; |
|
179 |
35 |
return true; |
|
180 |
} |
||
181 |
return false; |
||
182 |
} |
||
183 |
|||
184 |
8411 |
bool exists(FsEntry *restrict const entry, |
|
185 |
std::string fileName, |
||
186 |
std::string dirName A_UNUSED) |
||
187 |
{ |
||
188 |
16822 |
return Files::existsLocal(static_cast<DirEntry*>(entry)->rootSubDir + |
|
189 |
✓✗ | 16822 |
fileName); |
190 |
} |
||
191 |
|||
192 |
23 |
void enumerate(FsEntry *restrict const entry, |
|
193 |
std::string dirName, |
||
194 |
StringVect &names) |
||
195 |
{ |
||
196 |
const std::string path = static_cast<DirEntry*>(entry)->rootSubDir + |
||
197 |
46 |
dirName; |
|
198 |
23 |
const dirent *next_file = nullptr; |
|
199 |
✓✗ | 23 |
DIR *const dir = opendir(path.c_str()); |
200 |
✓✓ | 23 |
if (dir != nullptr) |
201 |
{ |
||
202 |
✓✗✓✓ |
328 |
while ((next_file = readdir(dir)) != nullptr) |
203 |
{ |
||
204 |
✓✗ | 1210 |
const std::string file = next_file->d_name; |
205 |
✓✓✓✓ ✓✓ |
605 |
if (file == "." || file == "..") |
206 |
34 |
continue; |
|
207 |
#ifndef WIN32 |
||
208 |
✓✓ | 277 |
if (mPermitLinks == false) |
209 |
{ |
||
210 |
struct stat statbuf; |
||
211 |
✓✗✓✗ ✓✗ |
651 |
if (lstat(path.c_str(), &statbuf) == 0 && |
212 |
217 |
S_ISLNK(statbuf.st_mode) != 0) |
|
213 |
{ |
||
214 |
continue; |
||
215 |
} |
||
216 |
} |
||
217 |
#endif // WIN32 |
||
218 |
|||
219 |
277 |
bool found(false); |
|
220 |
✓✓ | 4625 |
FOR_EACH (StringVectCIter, itn, names) |
221 |
{ |
||
222 |
✓✓ | 3245 |
if (*itn == file) |
223 |
{ |
||
224 |
found = true; |
||
225 |
break; |
||
226 |
} |
||
227 |
} |
||
228 |
✓✓ | 277 |
if (found == false) |
229 |
✓✗ | 272 |
names.push_back(file); |
230 |
} |
||
231 |
✓✗ | 17 |
closedir(dir); |
232 |
} |
||
233 |
23 |
} |
|
234 |
|||
235 |
888 |
bool isDirectory(FsEntry *restrict const entry, |
|
236 |
std::string dirName, |
||
237 |
bool &isDirFlag) |
||
238 |
{ |
||
239 |
1776 |
std::string path = static_cast<DirEntry*>(entry)->rootSubDir + dirName; |
|
240 |
|||
241 |
struct stat statbuf; |
||
242 |
✓✓ | 1776 |
if (stat(path.c_str(), &statbuf) == 0) |
243 |
{ |
||
244 |
464 |
isDirFlag = (S_ISDIR(statbuf.st_mode) != 0); |
|
245 |
464 |
return true; |
|
246 |
} |
||
247 |
return false; |
||
248 |
} |
||
249 |
|||
250 |
bool isSymbolicLink(std::string name) |
||
251 |
{ |
||
252 |
prepareFsPath(name); |
||
253 |
if (checkPath(name) == false) |
||
254 |
{ |
||
255 |
reportAlways("FsDir::isSymbolicLink invalid path: %s", |
||
256 |
name.c_str()) |
||
257 |
return false; |
||
258 |
} |
||
259 |
#ifndef WIN32 |
||
260 |
if (mPermitLinks == false) |
||
261 |
return false; |
||
262 |
|||
263 |
struct stat statbuf; |
||
264 |
return lstat(name.c_str(), &statbuf) == 0 && |
||
265 |
S_ISLNK(statbuf.st_mode) != 0; |
||
266 |
#else |
||
267 |
return false; |
||
268 |
#endif // WIN32 |
||
269 |
} |
||
270 |
|||
271 |
void freeList(List *restrict const handle) |
||
272 |
{ |
||
273 |
delete handle; |
||
274 |
} |
||
275 |
|||
276 |
bool setWriteDir(std::string newDir) |
||
277 |
{ |
||
278 |
prepareFsPath(newDir); |
||
279 |
mWriteDir = STD_MOVE(newDir); |
||
280 |
if (findLast(mWriteDir, std::string(dirSeparator)) == false) |
||
281 |
mWriteDir += dirSeparator; |
||
282 |
return true; |
||
283 |
} |
||
284 |
|||
285 |
bool mkdir(std::string dirname) |
||
286 |
{ |
||
287 |
prepareFsPath(dirname); |
||
288 |
if (mWriteDir.empty()) |
||
289 |
{ |
||
290 |
reportAlways("FsDir::mkdir write dir is empty") |
||
291 |
return false; |
||
292 |
} |
||
293 |
return mkdir_r((mWriteDir + dirname).c_str()) != -1; |
||
294 |
} |
||
295 |
|||
296 |
bool remove(std::string filename) |
||
297 |
{ |
||
298 |
prepareFsPath(filename); |
||
299 |
if (mWriteDir.empty()) |
||
300 |
{ |
||
301 |
reportAlways("FsDir::remove write dir is empty") |
||
302 |
return false; |
||
303 |
} |
||
304 |
return ::remove((mWriteDir + filename).c_str()) != 0; |
||
305 |
} |
||
306 |
|||
307 |
20 |
void permitLinks(const bool val) |
|
308 |
{ |
||
309 |
20 |
mPermitLinks = val; |
|
310 |
20 |
} |
|
311 |
|||
312 |
18 |
int close(File *restrict const file) |
|
313 |
{ |
||
314 |
✓✗ | 18 |
if (file == nullptr) |
315 |
return 0; |
||
316 |
18 |
delete file; |
|
317 |
18 |
return 1; |
|
318 |
} |
||
319 |
|||
320 |
6 |
int64_t read(File *restrict const file, |
|
321 |
void *restrict const buffer, |
||
322 |
const uint32_t objSize, |
||
323 |
const uint32_t objCount) |
||
324 |
{ |
||
325 |
✓✗ | 6 |
if (file == nullptr) |
326 |
return 0; |
||
327 |
6 |
FILEHTYPE fd = file->mFd; |
|
328 |
✗✓ | 6 |
if (fd == FILEHDEFAULT) |
329 |
{ |
||
330 |
reportAlways("FsDir::read file not opened.") |
||
331 |
return 0; |
||
332 |
} |
||
333 |
#ifdef USE_FILE_FOPEN |
||
334 |
12 |
return fread(buffer, objSize, objCount, fd); |
|
335 |
#else // USE_FILE_FOPEN |
||
336 |
int max = objSize * objCount; |
||
337 |
int cnt = ::read(fd, buffer, max); |
||
338 |
if (cnt <= 0) |
||
339 |
return cnt; |
||
340 |
return cnt / objSize; |
||
341 |
#endif // USE_FILE_FOPEN |
||
342 |
} |
||
343 |
|||
344 |
int64_t write(File *restrict const file, |
||
345 |
const void *restrict const buffer, |
||
346 |
const uint32_t objSize, |
||
347 |
const uint32_t objCount) |
||
348 |
{ |
||
349 |
if (file == nullptr) |
||
350 |
return 0; |
||
351 |
FILEHTYPE fd = file->mFd; |
||
352 |
if (fd == FILEHDEFAULT) |
||
353 |
{ |
||
354 |
reportAlways("FsDir::write file not opened.") |
||
355 |
return 0; |
||
356 |
} |
||
357 |
#ifdef USE_FILE_FOPEN |
||
358 |
return fwrite(buffer, objSize, objCount, fd); |
||
359 |
#else // USE_FILE_FOPEN |
||
360 |
int max = objSize * objCount; |
||
361 |
int cnt = ::write(fd, buffer, max); |
||
362 |
if (cnt <= 0) |
||
363 |
return cnt; |
||
364 |
return cnt / objSize; |
||
365 |
#endif // USE_FILE_FOPEN |
||
366 |
} |
||
367 |
|||
368 |
15 |
int64_t fileLength(File *restrict const file) |
|
369 |
{ |
||
370 |
✓✗ | 15 |
if (file == nullptr) |
371 |
return -1; |
||
372 |
15 |
FILEHTYPE fd = file->mFd; |
|
373 |
✗✓ | 15 |
if (fd == FILEHDEFAULT) |
374 |
{ |
||
375 |
reportAlways("FsDir::fileLength file not opened.") |
||
376 |
return 0; |
||
377 |
} |
||
378 |
#ifdef USE_FILE_FOPEN |
||
379 |
15 |
const long pos = ftell(fd); |
|
380 |
✗✓ | 15 |
if (pos < 0) |
381 |
{ |
||
382 |
reportAlways("FsDir::fileLength ftell error.") |
||
383 |
return -1; |
||
384 |
} |
||
385 |
15 |
fseek(fd, 0, SEEK_END); |
|
386 |
15 |
const long sz = ftell(fd); |
|
387 |
15 |
fseek(fd, pos, SEEK_SET); |
|
388 |
15 |
return sz; |
|
389 |
#else // USE_FILE_FOPEN |
||
390 |
struct stat statbuf; |
||
391 |
if (fstat(fd, &statbuf) == -1) |
||
392 |
{ |
||
393 |
reportAlways("FsDir::fileLength error.") |
||
394 |
return -1; |
||
395 |
} |
||
396 |
return static_cast<int64_t>(statbuf.st_size); |
||
397 |
#endif // USE_FILE_FOPEN |
||
398 |
} |
||
399 |
|||
400 |
6 |
int64_t tell(File *restrict const file) |
|
401 |
{ |
||
402 |
✓✗ | 6 |
if (file == nullptr) |
403 |
return -1; |
||
404 |
|||
405 |
6 |
FILEHTYPE fd = file->mFd; |
|
406 |
✗✓ | 6 |
if (fd == FILEHDEFAULT) |
407 |
{ |
||
408 |
reportAlways("FsDir::tell file not opened.") |
||
409 |
return 0; |
||
410 |
} |
||
411 |
#ifdef USE_FILE_FOPEN |
||
412 |
6 |
return ftell(fd); |
|
413 |
#else // USE_FILE_FOPEN |
||
414 |
return lseek(fd, 0, SEEK_CUR); |
||
415 |
#endif // USE_FILE_FOPEN |
||
416 |
} |
||
417 |
|||
418 |
3 |
int seek(File *restrict const file, |
|
419 |
const uint64_t pos) |
||
420 |
{ |
||
421 |
✓✗ | 3 |
if (file == nullptr) |
422 |
return 0; |
||
423 |
|||
424 |
3 |
FILEHTYPE fd = file->mFd; |
|
425 |
✗✓ | 3 |
if (fd == FILEHDEFAULT) |
426 |
{ |
||
427 |
reportAlways("FsDir::seek file not opened.") |
||
428 |
return 0; |
||
429 |
} |
||
430 |
3 |
const int64_t res = FILESEEK(fd, pos, SEEK_SET); |
|
431 |
✓✗ | 3 |
if (res == -1) |
432 |
return 0; |
||
433 |
3 |
return 1; |
|
434 |
} |
||
435 |
|||
436 |
9 |
int eof(File *restrict const file) |
|
437 |
{ |
||
438 |
✓✗ | 9 |
if (file == nullptr) |
439 |
return -1; |
||
440 |
|||
441 |
9 |
FILEHTYPE fd = file->mFd; |
|
442 |
✗✓ | 9 |
if (fd == FILEHDEFAULT) |
443 |
{ |
||
444 |
reportAlways("FsDir::eof file not opened.") |
||
445 |
return 0; |
||
446 |
} |
||
447 |
#ifdef USE_FILE_FOPEN |
||
448 |
9 |
const int flag = feof(fd); |
|
449 |
✓✗ | 9 |
if (flag != 0) |
450 |
return 1; |
||
451 |
9 |
const int64_t pos = ftell(fd); |
|
452 |
9 |
const int64_t len = fileLength(file); |
|
453 |
#else // USE_FILE_FOPEN |
||
454 |
const int64_t pos = lseek(fd, 0, SEEK_CUR); |
||
455 |
struct stat statbuf; |
||
456 |
if (fstat(fd, &statbuf) == -1) |
||
457 |
{ |
||
458 |
reportAlways("FsDir::fileLength error.") |
||
459 |
return -1; |
||
460 |
} |
||
461 |
const int64_t len = static_cast<int64_t>(statbuf.st_size); |
||
462 |
#endif // USE_FILE_FOPEN |
||
463 |
✓✗✓✓ |
9 |
return static_cast<int>(pos < 0 || len < 0 || pos >= len); |
464 |
} |
||
465 |
|||
466 |
4296 |
const char *loadFile(FsEntry *restrict const entry, |
|
467 |
std::string filename, |
||
468 |
int &restrict fileSize) |
||
469 |
{ |
||
470 |
4296 |
const DirEntry *const dirEntry = static_cast<DirEntry*>(entry); |
|
471 |
8592 |
const std::string path = dirEntry->rootSubDir + filename; |
|
472 |
✓✗✓✓ |
4296 |
if (Files::existsLocal(path) == false) |
473 |
return nullptr; |
||
474 |
✓✗ | 2422 |
FILEHTYPE fd = FILEOPEN(path.c_str(), |
475 |
FILEOPEN_FLAG_READ); |
||
476 |
✗✓ | 2422 |
if (fd == FILEHDEFAULT) |
477 |
{ |
||
478 |
reportAlways("VirtFs::loadFile file open error: %s", |
||
479 |
filename.c_str()) |
||
480 |
return nullptr; |
||
481 |
} |
||
482 |
|||
483 |
4844 |
logger->log("Loaded %s/%s", |
|
484 |
dirEntry->userDir.c_str(), |
||
485 |
✓✗ | 2422 |
filename.c_str()); |
486 |
|||
487 |
#ifdef USE_FILE_FOPEN |
||
488 |
2422 |
fseek(fd, 0, SEEK_END); |
|
489 |
✓✗ | 2422 |
const long sz = ftell(fd); |
490 |
✗✓ | 2422 |
if (sz < 0) |
491 |
{ |
||
492 |
reportAlways("FsDir::fileLength ftell error.") |
||
493 |
if (fd != FILEHDEFAULT) |
||
494 |
FILECLOSE(fd); |
||
495 |
return nullptr; |
||
496 |
} |
||
497 |
2422 |
fseek(fd, 0, SEEK_SET); |
|
498 |
2422 |
fileSize = static_cast<int>(sz); |
|
499 |
#else // USE_FILE_FOPEN |
||
500 |
struct stat statbuf; |
||
501 |
if (fstat(fd, &statbuf) == -1) |
||
502 |
{ |
||
503 |
reportAlways("FsDir::fileLength error.") |
||
504 |
if (fd != FILEHDEFAULT) |
||
505 |
FILECLOSE(fd); |
||
506 |
return nullptr; |
||
507 |
} |
||
508 |
fileSize = static_cast<int>(statbuf.st_size); |
||
509 |
#endif // USE_FILE_FOPEN |
||
510 |
|||
511 |
// Allocate memory and load the file |
||
512 |
✓✗ | 2422 |
char *restrict const buffer = new char[CAST_SIZE(fileSize)]; |
513 |
✓✗ | 2422 |
if (fileSize > 0) |
514 |
2422 |
buffer[fileSize - 1] = 0; |
|
515 |
|||
516 |
#ifdef USE_FILE_FOPEN |
||
517 |
4844 |
const int cnt = CAST_S32(fread(buffer, 1, fileSize, fd)); |
|
518 |
#else // USE_FILE_FOPEN |
||
519 |
const int cnt = ::read(fd, buffer, fileSize); |
||
520 |
#endif // USE_FILE_FOPEN |
||
521 |
|||
522 |
✗✓ | 2422 |
if (cnt <= 0) |
523 |
{ |
||
524 |
delete [] buffer; |
||
525 |
if (fd != FILEHDEFAULT) |
||
526 |
FILECLOSE(fd); |
||
527 |
return nullptr; |
||
528 |
} |
||
529 |
|||
530 |
if (fd != FILEHDEFAULT) |
||
531 |
✓✗ | 2422 |
FILECLOSE(fd); |
532 |
|||
533 |
return buffer; |
||
534 |
} |
||
535 |
|||
536 |
13 |
void getFiles(FsEntry *restrict const entry, |
|
537 |
std::string dirName, |
||
538 |
StringVect &names) |
||
539 |
{ |
||
540 |
const std::string path = static_cast<DirEntry*>(entry)->rootSubDir + |
||
541 |
26 |
dirName; |
|
542 |
13 |
const dirent *next_file = nullptr; |
|
543 |
✓✗ | 13 |
DIR *const dir = opendir(path.c_str()); |
544 |
✓✓ | 13 |
if (dir != nullptr) |
545 |
{ |
||
546 |
✓✗✓✓ |
339 |
while ((next_file = readdir(dir)) != nullptr) |
547 |
{ |
||
548 |
struct stat statbuf; |
||
549 |
✓✗ | 1261 |
const std::string file = next_file->d_name; |
550 |
✓✓✓✓ ✓✓ |
645 |
if (file == "." || file == "..") |
551 |
51 |
continue; |
|
552 |
#ifndef WIN32 |
||
553 |
✓✓ | 306 |
if (mPermitLinks == false) |
554 |
{ |
||
555 |
✓✗✓✗ ✓✗ |
540 |
if (lstat(path.c_str(), &statbuf) == 0 && |
556 |
180 |
S_ISLNK(statbuf.st_mode) != 0) |
|
557 |
{ |
||
558 |
continue; |
||
559 |
} |
||
560 |
} |
||
561 |
#endif // WIN32 |
||
562 |
|||
563 |
✓✗ | 889 |
const std::string filePath = pathJoin(path, file); |
564 |
✓✗ | 612 |
if (stat(filePath.c_str(), &statbuf) == 0) |
565 |
{ |
||
566 |
✓✓✓✓ |
306 |
if (S_ISDIR(statbuf.st_mode) != 0) |
567 |
continue; |
||
568 |
} |
||
569 |
|||
570 |
277 |
bool found(false); |
|
571 |
✓✓ | 4816 |
FOR_EACH (StringVectCIter, itn, names) |
572 |
{ |
||
573 |
✓✗ | 3431 |
if (*itn == file) |
574 |
{ |
||
575 |
found = true; |
||
576 |
break; |
||
577 |
} |
||
578 |
} |
||
579 |
✓✗ | 277 |
if (found == false) |
580 |
✓✗ | 277 |
names.push_back(file); |
581 |
} |
||
582 |
✓✗ | 11 |
closedir(dir); |
583 |
} |
||
584 |
13 |
} |
|
585 |
|||
586 |
173 |
void getFilesWithDir(FsEntry *restrict const entry, |
|
587 |
const std::string &dirName, |
||
588 |
StringVect &names) |
||
589 |
{ |
||
590 |
const std::string path = static_cast<DirEntry*>(entry)->rootSubDir + |
||
591 |
346 |
dirName; |
|
592 |
173 |
const dirent *next_file = nullptr; |
|
593 |
✓✗ | 173 |
DIR *const dir = opendir(path.c_str()); |
594 |
✓✓ | 173 |
if (dir != nullptr) |
595 |
{ |
||
596 |
✓✗✓✓ |
137 |
while ((next_file = readdir(dir)) != nullptr) |
597 |
{ |
||
598 |
struct stat statbuf; |
||
599 |
✓✗ | 485 |
const std::string file = next_file->d_name; |
600 |
✓✓✓✓ ✓✓ |
247 |
if (file == "." || file == "..") |
601 |
27 |
continue; |
|
602 |
#ifndef WIN32 |
||
603 |
✓✗ | 110 |
if (mPermitLinks == false) |
604 |
{ |
||
605 |
✓✗✓✗ ✓✗ |
330 |
if (lstat(path.c_str(), &statbuf) == 0 && |
606 |
110 |
S_ISLNK(statbuf.st_mode) != 0) |
|
607 |
{ |
||
608 |
continue; |
||
609 |
} |
||
610 |
} |
||
611 |
#endif // WIN32 |
||
612 |
|||
613 |
✓✗ | 321 |
const std::string filePath = pathJoin(path, file); |
614 |
✓✗ | 220 |
if (stat(filePath.c_str(), &statbuf) == 0) |
615 |
{ |
||
616 |
✓✓✓✓ |
110 |
if (S_ISDIR(statbuf.st_mode) != 0) |
617 |
continue; |
||
618 |
} |
||
619 |
|||
620 |
101 |
bool found(false); |
|
621 |
✓✓ | 1266 |
FOR_EACH (StringVectCIter, itn, names) |
622 |
{ |
||
623 |
✓✗ | 761 |
if (*itn == file) |
624 |
{ |
||
625 |
found = true; |
||
626 |
break; |
||
627 |
} |
||
628 |
} |
||
629 |
✓✗ | 101 |
if (found == false) |
630 |
✓✗ | 404 |
names.push_back(pathJoin(dirName, file)); |
631 |
} |
||
632 |
✓✗ | 9 |
closedir(dir); |
633 |
} |
||
634 |
173 |
} |
|
635 |
|||
636 |
10 |
void getDirs(FsEntry *restrict const entry, |
|
637 |
std::string dirName, |
||
638 |
StringVect &names) |
||
639 |
{ |
||
640 |
const std::string path = static_cast<DirEntry*>(entry)->rootSubDir + |
||
641 |
20 |
dirName; |
|
642 |
10 |
const dirent *next_file = nullptr; |
|
643 |
✓✗ | 10 |
DIR *const dir = opendir(path.c_str()); |
644 |
✓✓ | 10 |
if (dir != nullptr) |
645 |
{ |
||
646 |
✓✗✓✓ |
139 |
while ((next_file = readdir(dir)) != nullptr) |
647 |
{ |
||
648 |
struct stat statbuf; |
||
649 |
✓✗ | 424 |
const std::string file = next_file->d_name; |
650 |
✓✓✓✓ ✓✓ |
254 |
if (file == "." || file == "..") |
651 |
100 |
continue; |
|
652 |
#ifndef WIN32 |
||
653 |
✓✗ | 115 |
if (mPermitLinks == false) |
654 |
{ |
||
655 |
✓✗✓✗ ✓✗ |
345 |
if (lstat(path.c_str(), &statbuf) == 0 && |
656 |
115 |
S_ISLNK(statbuf.st_mode) != 0) |
|
657 |
{ |
||
658 |
continue; |
||
659 |
} |
||
660 |
} |
||
661 |
#endif // WIN32 |
||
662 |
|||
663 |
✓✗ | 261 |
const std::string filePath = pathJoin(path, file); |
664 |
✓✗ | 230 |
if (stat(filePath.c_str(), &statbuf) == 0) |
665 |
{ |
||
666 |
✓✓ | 115 |
if (S_ISDIR(statbuf.st_mode) == 0) |
667 |
continue; |
||
668 |
} |
||
669 |
|||
670 |
31 |
bool found(false); |
|
671 |
✓✓ | 294 |
FOR_EACH (StringVectCIter, itn, names) |
672 |
{ |
||
673 |
✓✗ | 139 |
if (*itn == file) |
674 |
{ |
||
675 |
found = true; |
||
676 |
break; |
||
677 |
} |
||
678 |
} |
||
679 |
✓✗ | 31 |
if (found == false) |
680 |
✓✗ | 31 |
names.push_back(file); |
681 |
} |
||
682 |
✓✗ | 8 |
closedir(dir); |
683 |
} |
||
684 |
10 |
} |
|
685 |
} // namespace FsDir |
||
686 |
|||
687 |
✓✗✓✗ |
3 |
} // namespace VirtFs |
Generated by: GCOVR (Version 3.3) |