|
1 /* |
|
2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 #include "FilePath.h" |
|
27 |
|
28 #include <algorithm> |
|
29 #include <list> |
|
30 |
|
31 #ifdef WINDOWS |
|
32 #include <ShellAPI.h> |
|
33 #endif // WINDOWS |
|
34 |
|
35 #ifdef POSIX |
|
36 #include <sys/stat.h> |
|
37 #endif // POSIX |
|
38 |
|
39 |
|
40 bool FilePath::FileExists(const TString FileName) { |
|
41 bool result = false; |
|
42 #ifdef WINDOWS |
|
43 WIN32_FIND_DATA FindFileData; |
|
44 TString fileName = FixPathForPlatform(FileName); |
|
45 HANDLE handle = FindFirstFile(fileName.data(), &FindFileData); |
|
46 |
|
47 if (handle != INVALID_HANDLE_VALUE) { |
|
48 if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) { |
|
49 result = true; |
|
50 } |
|
51 else { |
|
52 result = true; |
|
53 } |
|
54 |
|
55 FindClose(handle); |
|
56 } |
|
57 #endif // WINDOWS |
|
58 #ifdef POSIX |
|
59 struct stat buf; |
|
60 |
|
61 if ((stat(StringToFileSystemString(FileName), &buf) == 0) && |
|
62 (S_ISREG(buf.st_mode) != 0)) { |
|
63 result = true; |
|
64 } |
|
65 #endif // POSIX |
|
66 return result; |
|
67 } |
|
68 |
|
69 bool FilePath::DirectoryExists(const TString DirectoryName) { |
|
70 bool result = false; |
|
71 #ifdef WINDOWS |
|
72 WIN32_FIND_DATA FindFileData; |
|
73 TString directoryName = FixPathForPlatform(DirectoryName); |
|
74 HANDLE handle = FindFirstFile(directoryName.data(), &FindFileData); |
|
75 |
|
76 if (handle != INVALID_HANDLE_VALUE) { |
|
77 if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) { |
|
78 result = true; |
|
79 } |
|
80 |
|
81 FindClose(handle); |
|
82 } |
|
83 #endif // WINDOWS |
|
84 #ifdef POSIX |
|
85 struct stat buf; |
|
86 |
|
87 if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) && |
|
88 (S_ISDIR(buf.st_mode) != 0)) { |
|
89 result = true; |
|
90 } |
|
91 #endif // POSIX |
|
92 return result; |
|
93 } |
|
94 |
|
95 #ifdef WINDOWS |
|
96 std::string GetLastErrorAsString() { |
|
97 // Get the error message, if any. |
|
98 DWORD errorMessageID = ::GetLastError(); |
|
99 |
|
100 if (errorMessageID == 0) { |
|
101 return "No error message has been recorded"; |
|
102 } |
|
103 |
|
104 LPSTR messageBuffer = NULL; |
|
105 size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
106 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
|
107 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, |
|
108 SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); |
|
109 |
|
110 std::string message(messageBuffer, size); |
|
111 |
|
112 // Free the buffer. |
|
113 LocalFree(messageBuffer); |
|
114 |
|
115 return message; |
|
116 } |
|
117 #endif // WINDOWS |
|
118 |
|
119 bool FilePath::DeleteFile(const TString FileName) { |
|
120 bool result = false; |
|
121 |
|
122 if (FileExists(FileName) == true) { |
|
123 #ifdef WINDOWS |
|
124 TString lFileName = FixPathForPlatform(FileName); |
|
125 FileAttributes attributes(lFileName); |
|
126 |
|
127 if (attributes.Contains(faReadOnly) == true) { |
|
128 attributes.Remove(faReadOnly); |
|
129 } |
|
130 |
|
131 result = ::DeleteFile(lFileName.data()) == TRUE; |
|
132 #endif // WINDOWS |
|
133 #ifdef POSIX |
|
134 if (unlink(StringToFileSystemString(FileName)) == 0) { |
|
135 result = true; |
|
136 } |
|
137 #endif // POSIX |
|
138 } |
|
139 |
|
140 return result; |
|
141 } |
|
142 |
|
143 bool FilePath::DeleteDirectory(const TString DirectoryName) { |
|
144 bool result = false; |
|
145 |
|
146 if (DirectoryExists(DirectoryName) == true) { |
|
147 #ifdef WINDOWS |
|
148 SHFILEOPSTRUCTW fos = {0}; |
|
149 TString directoryName = FixPathForPlatform(DirectoryName); |
|
150 DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2); |
|
151 if (lDirectoryName.GetData() == NULL) { |
|
152 return false; |
|
153 } |
|
154 memcpy(lDirectoryName.GetData(), directoryName.data(), (directoryName.size() + 2) * sizeof(TCHAR)); |
|
155 lDirectoryName[directoryName.size() + 1] = NULL; |
|
156 // Double null terminate for SHFileOperation. |
|
157 |
|
158 // Delete the folder and everything inside. |
|
159 fos.wFunc = FO_DELETE; |
|
160 fos.pFrom = lDirectoryName.GetData(); |
|
161 fos.fFlags = FOF_NO_UI; |
|
162 result = SHFileOperation(&fos) == 0; |
|
163 #endif // WINDOWS |
|
164 #ifdef POSIX |
|
165 if (unlink(StringToFileSystemString(DirectoryName)) == 0) { |
|
166 result = true; |
|
167 } |
|
168 #endif // POSIX |
|
169 } |
|
170 |
|
171 return result; |
|
172 } |
|
173 |
|
174 TString FilePath::IncludeTrailingSeparator(const TString value) { |
|
175 TString result = value; |
|
176 |
|
177 if (value.size() > 0) { |
|
178 TString::iterator i = result.end(); |
|
179 i--; |
|
180 |
|
181 if (*i != TRAILING_PATHSEPARATOR) { |
|
182 result += TRAILING_PATHSEPARATOR; |
|
183 } |
|
184 } |
|
185 |
|
186 return result; |
|
187 } |
|
188 |
|
189 TString FilePath::IncludeTrailingSeparator(const char* value) { |
|
190 TString lvalue = PlatformString(value).toString(); |
|
191 return IncludeTrailingSeparator(lvalue); |
|
192 } |
|
193 |
|
194 TString FilePath::IncludeTrailingSeparator(const wchar_t* value) { |
|
195 TString lvalue = PlatformString(value).toString(); |
|
196 return IncludeTrailingSeparator(lvalue); |
|
197 } |
|
198 |
|
199 TString FilePath::ExtractFilePath(TString Path) { |
|
200 #ifdef WINDOWS |
|
201 TString result; |
|
202 size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR); |
|
203 if (slash != TString::npos) |
|
204 result = Path.substr(0, slash); |
|
205 return result; |
|
206 #endif // WINDOWS |
|
207 #ifdef POSIX |
|
208 return dirname(StringToFileSystemString(Path)); |
|
209 #endif // POSIX |
|
210 } |
|
211 |
|
212 TString FilePath::ExtractFileExt(TString Path) { |
|
213 TString result; |
|
214 size_t dot = Path.find_last_of('.'); |
|
215 |
|
216 if (dot != TString::npos) { |
|
217 result = Path.substr(dot, Path.size() - dot); |
|
218 } |
|
219 |
|
220 return result; |
|
221 } |
|
222 |
|
223 TString FilePath::ExtractFileName(TString Path) { |
|
224 #ifdef WINDOWS |
|
225 TString result; |
|
226 |
|
227 size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR); |
|
228 if (slash != TString::npos) |
|
229 result = Path.substr(slash + 1, Path.size() - slash - 1); |
|
230 |
|
231 return result; |
|
232 #endif // WINDOWS |
|
233 #ifdef POSIX |
|
234 return basename(StringToFileSystemString(Path)); |
|
235 #endif // POSIX |
|
236 } |
|
237 |
|
238 TString FilePath::ChangeFileExt(TString Path, TString Extension) { |
|
239 TString result; |
|
240 size_t dot = Path.find_last_of('.'); |
|
241 |
|
242 if (dot != TString::npos) { |
|
243 result = Path.substr(0, dot) + Extension; |
|
244 } |
|
245 |
|
246 if (result.empty() == true) { |
|
247 result = Path; |
|
248 } |
|
249 |
|
250 return result; |
|
251 } |
|
252 |
|
253 TString FilePath::FixPathForPlatform(TString Path) { |
|
254 TString result = Path; |
|
255 std::replace(result.begin(), result.end(), |
|
256 BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR); |
|
257 #ifdef WINDOWS |
|
258 // The maximum path that does not require long path prefix. On Windows the |
|
259 // maximum path is 260 minus 1 (NUL) but for directories it is 260 minus |
|
260 // 12 minus 1 (to allow for the creation of a 8.3 file in the directory). |
|
261 const int maxPath = 247; |
|
262 if (result.length() > maxPath && |
|
263 result.find(_T("\\\\?\\")) == TString::npos && |
|
264 result.find(_T("\\\\?\\UNC")) == TString::npos) { |
|
265 const TString prefix(_T("\\\\")); |
|
266 if (!result.compare(0, prefix.size(), prefix)) { |
|
267 // UNC path, converting to UNC path in long notation |
|
268 result = _T("\\\\?\\UNC") + result.substr(1, result.length()); |
|
269 } else { |
|
270 // converting to non-UNC path in long notation |
|
271 result = _T("\\\\?\\") + result; |
|
272 } |
|
273 } |
|
274 #endif // WINDOWS |
|
275 return result; |
|
276 } |
|
277 |
|
278 TString FilePath::FixPathSeparatorForPlatform(TString Path) { |
|
279 TString result = Path; |
|
280 std::replace(result.begin(), result.end(), |
|
281 BAD_PATH_SEPARATOR, PATH_SEPARATOR); |
|
282 return result; |
|
283 } |
|
284 |
|
285 TString FilePath::PathSeparator() { |
|
286 TString result; |
|
287 result = PATH_SEPARATOR; |
|
288 return result; |
|
289 } |
|
290 |
|
291 bool FilePath::CreateDirectory(TString Path, bool ownerOnly) { |
|
292 bool result = false; |
|
293 |
|
294 std::list<TString> paths; |
|
295 TString lpath = Path; |
|
296 |
|
297 while (lpath.empty() == false && DirectoryExists(lpath) == false) { |
|
298 paths.push_front(lpath); |
|
299 lpath = ExtractFilePath(lpath); |
|
300 } |
|
301 |
|
302 for (std::list<TString>::iterator iterator = paths.begin(); |
|
303 iterator != paths.end(); iterator++) { |
|
304 lpath = *iterator; |
|
305 |
|
306 #ifdef WINDOWS |
|
307 if (_wmkdir(lpath.data()) == 0) { |
|
308 #endif // WINDOWS |
|
309 #ifdef POSIX |
|
310 mode_t mode = S_IRWXU; |
|
311 if (!ownerOnly) { |
|
312 mode |= S_IRWXG | S_IROTH | S_IXOTH; |
|
313 } |
|
314 if (mkdir(StringToFileSystemString(lpath), mode) == 0) { |
|
315 #endif // POSIX |
|
316 result = true; |
|
317 } |
|
318 else { |
|
319 result = false; |
|
320 break; |
|
321 } |
|
322 } |
|
323 |
|
324 return result; |
|
325 } |
|
326 |
|
327 void FilePath::ChangePermissions(TString FileName, bool ownerOnly) { |
|
328 #ifdef POSIX |
|
329 mode_t mode = S_IRWXU; |
|
330 if (!ownerOnly) { |
|
331 mode |= S_IRWXG | S_IROTH | S_IXOTH; |
|
332 } |
|
333 chmod(FileName.data(), mode); |
|
334 #endif // POSIX |
|
335 } |
|
336 |
|
337 //---------------------------------------------------------------------------- |
|
338 |
|
339 #include <algorithm> |
|
340 |
|
341 FileAttributes::FileAttributes(const TString FileName, bool FollowLink) { |
|
342 FFileName = FileName; |
|
343 FFollowLink = FollowLink; |
|
344 ReadAttributes(); |
|
345 } |
|
346 |
|
347 bool FileAttributes::WriteAttributes() { |
|
348 bool result = false; |
|
349 |
|
350 #ifdef WINDOWS |
|
351 DWORD attributes = 0; |
|
352 |
|
353 for (std::vector<FileAttribute>::const_iterator iterator = |
|
354 FAttributes.begin(); |
|
355 iterator != FAttributes.end(); iterator++) { |
|
356 switch (*iterator) { |
|
357 case faArchive: { |
|
358 attributes = attributes & FILE_ATTRIBUTE_ARCHIVE; |
|
359 break; |
|
360 } |
|
361 case faCompressed: { |
|
362 attributes = attributes & FILE_ATTRIBUTE_COMPRESSED; |
|
363 break; |
|
364 } |
|
365 case faDevice: { |
|
366 attributes = attributes & FILE_ATTRIBUTE_DEVICE; |
|
367 break; |
|
368 } |
|
369 case faDirectory: { |
|
370 attributes = attributes & FILE_ATTRIBUTE_DIRECTORY; |
|
371 break; |
|
372 } |
|
373 case faEncrypted: { |
|
374 attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED; |
|
375 break; |
|
376 } |
|
377 case faHidden: { |
|
378 attributes = attributes & FILE_ATTRIBUTE_HIDDEN; |
|
379 break; |
|
380 } |
|
381 case faNormal: { |
|
382 attributes = attributes & FILE_ATTRIBUTE_NORMAL; |
|
383 break; |
|
384 } |
|
385 case faNotContentIndexed: { |
|
386 attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; |
|
387 break; |
|
388 } |
|
389 case faOffline: { |
|
390 attributes = attributes & FILE_ATTRIBUTE_OFFLINE; |
|
391 break; |
|
392 } |
|
393 case faSystem: { |
|
394 attributes = attributes & FILE_ATTRIBUTE_SYSTEM; |
|
395 break; |
|
396 } |
|
397 case faSymbolicLink: { |
|
398 attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT; |
|
399 break; |
|
400 } |
|
401 case faSparceFile: { |
|
402 attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE; |
|
403 break; |
|
404 } |
|
405 case faReadOnly: { |
|
406 attributes = attributes & FILE_ATTRIBUTE_READONLY; |
|
407 break; |
|
408 } |
|
409 case faTemporary: { |
|
410 attributes = attributes & FILE_ATTRIBUTE_TEMPORARY; |
|
411 break; |
|
412 } |
|
413 case faVirtual: { |
|
414 attributes = attributes & FILE_ATTRIBUTE_VIRTUAL; |
|
415 break; |
|
416 } |
|
417 } |
|
418 } |
|
419 |
|
420 if (::SetFileAttributes(FFileName.data(), attributes) != 0) { |
|
421 result = true; |
|
422 } |
|
423 #endif // WINDOWS |
|
424 #ifdef POSIX |
|
425 mode_t attributes = 0; |
|
426 |
|
427 for (std::vector<FileAttribute>::const_iterator iterator = |
|
428 FAttributes.begin(); |
|
429 iterator != FAttributes.end(); iterator++) { |
|
430 switch (*iterator) { |
|
431 case faBlockSpecial: { |
|
432 attributes |= S_IFBLK; |
|
433 break; |
|
434 } |
|
435 case faCharacterSpecial: { |
|
436 attributes |= S_IFCHR; |
|
437 break; |
|
438 } |
|
439 case faFIFOSpecial: { |
|
440 attributes |= S_IFIFO; |
|
441 break; |
|
442 } |
|
443 case faNormal: { |
|
444 attributes |= S_IFREG; |
|
445 break; |
|
446 } |
|
447 case faDirectory: { |
|
448 attributes |= S_IFDIR; |
|
449 break; |
|
450 } |
|
451 case faSymbolicLink: { |
|
452 attributes |= S_IFLNK; |
|
453 break; |
|
454 } |
|
455 case faSocket: { |
|
456 attributes |= S_IFSOCK; |
|
457 break; |
|
458 } |
|
459 |
|
460 // Owner |
|
461 case faReadOnly: { |
|
462 attributes |= S_IRUSR; |
|
463 break; |
|
464 } |
|
465 case faWriteOnly: { |
|
466 attributes |= S_IWUSR; |
|
467 break; |
|
468 } |
|
469 case faReadWrite: { |
|
470 attributes |= S_IRUSR; |
|
471 attributes |= S_IWUSR; |
|
472 break; |
|
473 } |
|
474 case faExecute: { |
|
475 attributes |= S_IXUSR; |
|
476 break; |
|
477 } |
|
478 |
|
479 // Group |
|
480 case faGroupReadOnly: { |
|
481 attributes |= S_IRGRP; |
|
482 break; |
|
483 } |
|
484 case faGroupWriteOnly: { |
|
485 attributes |= S_IWGRP; |
|
486 break; |
|
487 } |
|
488 case faGroupReadWrite: { |
|
489 attributes |= S_IRGRP; |
|
490 attributes |= S_IWGRP; |
|
491 break; |
|
492 } |
|
493 case faGroupExecute: { |
|
494 attributes |= S_IXGRP; |
|
495 break; |
|
496 } |
|
497 |
|
498 // Others |
|
499 case faOthersReadOnly: { |
|
500 attributes |= S_IROTH; |
|
501 break; |
|
502 } |
|
503 case faOthersWriteOnly: { |
|
504 attributes |= S_IWOTH; |
|
505 break; |
|
506 } |
|
507 case faOthersReadWrite: { |
|
508 attributes |= S_IROTH; |
|
509 attributes |= S_IWOTH; |
|
510 break; |
|
511 } |
|
512 case faOthersExecute: { |
|
513 attributes |= S_IXOTH; |
|
514 break; |
|
515 } |
|
516 default: |
|
517 break; |
|
518 } |
|
519 } |
|
520 |
|
521 if (chmod(FFileName.data(), attributes) == 0) { |
|
522 result = true; |
|
523 } |
|
524 #endif // POSIX |
|
525 |
|
526 return result; |
|
527 } |
|
528 |
|
529 #define S_ISRUSR(m) (((m) & S_IRWXU) == S_IRUSR) |
|
530 #define S_ISWUSR(m) (((m) & S_IRWXU) == S_IWUSR) |
|
531 #define S_ISXUSR(m) (((m) & S_IRWXU) == S_IXUSR) |
|
532 |
|
533 #define S_ISRGRP(m) (((m) & S_IRWXG) == S_IRGRP) |
|
534 #define S_ISWGRP(m) (((m) & S_IRWXG) == S_IWGRP) |
|
535 #define S_ISXGRP(m) (((m) & S_IRWXG) == S_IXGRP) |
|
536 |
|
537 #define S_ISROTH(m) (((m) & S_IRWXO) == S_IROTH) |
|
538 #define S_ISWOTH(m) (((m) & S_IRWXO) == S_IWOTH) |
|
539 #define S_ISXOTH(m) (((m) & S_IRWXO) == S_IXOTH) |
|
540 |
|
541 bool FileAttributes::ReadAttributes() { |
|
542 bool result = false; |
|
543 |
|
544 #ifdef WINDOWS |
|
545 DWORD attributes = ::GetFileAttributes(FFileName.data()); |
|
546 |
|
547 if (attributes != INVALID_FILE_ATTRIBUTES) { |
|
548 result = true; |
|
549 |
|
550 if (attributes | FILE_ATTRIBUTE_ARCHIVE) { |
|
551 FAttributes.push_back(faArchive); |
|
552 } |
|
553 if (attributes | FILE_ATTRIBUTE_COMPRESSED) { |
|
554 FAttributes.push_back(faCompressed); |
|
555 } |
|
556 if (attributes | FILE_ATTRIBUTE_DEVICE) { |
|
557 FAttributes.push_back(faDevice); |
|
558 } |
|
559 if (attributes | FILE_ATTRIBUTE_DIRECTORY) { |
|
560 FAttributes.push_back(faDirectory); |
|
561 } |
|
562 if (attributes | FILE_ATTRIBUTE_ENCRYPTED) { |
|
563 FAttributes.push_back(faEncrypted); |
|
564 } |
|
565 if (attributes | FILE_ATTRIBUTE_HIDDEN) { |
|
566 FAttributes.push_back(faHidden); |
|
567 } |
|
568 // if (attributes | FILE_ATTRIBUTE_INTEGRITY_STREAM) { |
|
569 // FAttributes.push_back(faIntegrityStream); |
|
570 // } |
|
571 if (attributes | FILE_ATTRIBUTE_NORMAL) { |
|
572 FAttributes.push_back(faNormal); |
|
573 } |
|
574 if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) { |
|
575 FAttributes.push_back(faNotContentIndexed); |
|
576 } |
|
577 // if (attributes | FILE_ATTRIBUTE_NO_SCRUB_DATA) { |
|
578 // FAttributes.push_back(faNoScrubData); |
|
579 // } |
|
580 if (attributes | FILE_ATTRIBUTE_SYSTEM) { |
|
581 FAttributes.push_back(faSystem); |
|
582 } |
|
583 if (attributes | FILE_ATTRIBUTE_OFFLINE) { |
|
584 FAttributes.push_back(faOffline); |
|
585 } |
|
586 if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) { |
|
587 FAttributes.push_back(faSymbolicLink); |
|
588 } |
|
589 if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) { |
|
590 FAttributes.push_back(faSparceFile); |
|
591 } |
|
592 if (attributes | FILE_ATTRIBUTE_READONLY ) { |
|
593 FAttributes.push_back(faReadOnly); |
|
594 } |
|
595 if (attributes | FILE_ATTRIBUTE_TEMPORARY) { |
|
596 FAttributes.push_back(faTemporary); |
|
597 } |
|
598 if (attributes | FILE_ATTRIBUTE_VIRTUAL) { |
|
599 FAttributes.push_back(faVirtual); |
|
600 } |
|
601 } |
|
602 #endif // WINDOWS |
|
603 #ifdef POSIX |
|
604 struct stat status; |
|
605 |
|
606 if (stat(StringToFileSystemString(FFileName), &status) == 0) { |
|
607 result = true; |
|
608 |
|
609 if (S_ISBLK(status.st_mode) != 0) { |
|
610 FAttributes.push_back(faBlockSpecial); |
|
611 } |
|
612 if (S_ISCHR(status.st_mode) != 0) { |
|
613 FAttributes.push_back(faCharacterSpecial); |
|
614 } |
|
615 if (S_ISFIFO(status.st_mode) != 0) { |
|
616 FAttributes.push_back(faFIFOSpecial); |
|
617 } |
|
618 if (S_ISREG(status.st_mode) != 0) { |
|
619 FAttributes.push_back(faNormal); |
|
620 } |
|
621 if (S_ISDIR(status.st_mode) != 0) { |
|
622 FAttributes.push_back(faDirectory); |
|
623 } |
|
624 if (S_ISLNK(status.st_mode) != 0) { |
|
625 FAttributes.push_back(faSymbolicLink); |
|
626 } |
|
627 if (S_ISSOCK(status.st_mode) != 0) { |
|
628 FAttributes.push_back(faSocket); |
|
629 } |
|
630 |
|
631 // Owner |
|
632 if (S_ISRUSR(status.st_mode) != 0) { |
|
633 if (S_ISWUSR(status.st_mode) != 0) { |
|
634 FAttributes.push_back(faReadWrite); |
|
635 } else { |
|
636 FAttributes.push_back(faReadOnly); |
|
637 } |
|
638 } else if (S_ISWUSR(status.st_mode) != 0) { |
|
639 FAttributes.push_back(faWriteOnly); |
|
640 } |
|
641 |
|
642 if (S_ISXUSR(status.st_mode) != 0) { |
|
643 FAttributes.push_back(faExecute); |
|
644 } |
|
645 |
|
646 // Group |
|
647 if (S_ISRGRP(status.st_mode) != 0) { |
|
648 if (S_ISWGRP(status.st_mode) != 0) { |
|
649 FAttributes.push_back(faGroupReadWrite); |
|
650 } else { |
|
651 FAttributes.push_back(faGroupReadOnly); |
|
652 } |
|
653 } else if (S_ISWGRP(status.st_mode) != 0) { |
|
654 FAttributes.push_back(faGroupWriteOnly); |
|
655 } |
|
656 |
|
657 if (S_ISXGRP(status.st_mode) != 0) { |
|
658 FAttributes.push_back(faGroupExecute); |
|
659 } |
|
660 |
|
661 |
|
662 // Others |
|
663 if (S_ISROTH(status.st_mode) != 0) { |
|
664 if (S_ISWOTH(status.st_mode) != 0) { |
|
665 FAttributes.push_back(faOthersReadWrite); |
|
666 } else { |
|
667 FAttributes.push_back(faOthersReadOnly); |
|
668 } |
|
669 } |
|
670 else if (S_ISWOTH(status.st_mode) != 0) { |
|
671 FAttributes.push_back(faOthersWriteOnly); |
|
672 } |
|
673 |
|
674 if (S_ISXOTH(status.st_mode) != 0) { |
|
675 FAttributes.push_back(faOthersExecute); |
|
676 } |
|
677 |
|
678 if (FFileName.size() > 0 && FFileName[0] == '.') { |
|
679 FAttributes.push_back(faHidden); |
|
680 } |
|
681 } |
|
682 #endif // POSIX |
|
683 |
|
684 return result; |
|
685 } |
|
686 |
|
687 bool FileAttributes::Valid(const FileAttribute Value) { |
|
688 bool result = false; |
|
689 |
|
690 switch (Value) { |
|
691 #ifdef WINDOWS |
|
692 case faHidden: |
|
693 #endif // WINDOWS |
|
694 #ifdef POSIX |
|
695 case faReadWrite: |
|
696 case faWriteOnly: |
|
697 case faExecute: |
|
698 |
|
699 case faGroupReadWrite: |
|
700 case faGroupWriteOnly: |
|
701 case faGroupReadOnly: |
|
702 case faGroupExecute: |
|
703 |
|
704 case faOthersReadWrite: |
|
705 case faOthersWriteOnly: |
|
706 case faOthersReadOnly: |
|
707 case faOthersExecute: |
|
708 #endif // POSIX |
|
709 |
|
710 case faReadOnly: { |
|
711 result = true; |
|
712 break; |
|
713 } |
|
714 default: |
|
715 break; |
|
716 } |
|
717 |
|
718 return result; |
|
719 } |
|
720 |
|
721 void FileAttributes::Append(FileAttribute Value) { |
|
722 if (Valid(Value) == true) { |
|
723 #ifdef POSIX |
|
724 if ((Value == faReadOnly && Contains(faWriteOnly) == true) || |
|
725 (Value == faWriteOnly && Contains(faReadOnly) == true)) { |
|
726 Value = faReadWrite; |
|
727 } |
|
728 #endif // POSIX |
|
729 |
|
730 FAttributes.push_back(Value); |
|
731 WriteAttributes(); |
|
732 } |
|
733 } |
|
734 |
|
735 bool FileAttributes::Contains(FileAttribute Value) { |
|
736 bool result = false; |
|
737 |
|
738 std::vector<FileAttribute>::const_iterator iterator = |
|
739 std::find(FAttributes.begin(), FAttributes.end(), Value); |
|
740 |
|
741 if (iterator != FAttributes.end()) { |
|
742 result = true; |
|
743 } |
|
744 |
|
745 return result; |
|
746 } |
|
747 |
|
748 void FileAttributes::Remove(FileAttribute Value) { |
|
749 if (Valid(Value) == true) { |
|
750 #ifdef POSIX |
|
751 if (Value == faReadOnly && Contains(faReadWrite) == true) { |
|
752 Append(faWriteOnly); |
|
753 Remove(faReadWrite); |
|
754 } |
|
755 else if (Value == faWriteOnly && Contains(faReadWrite) == true) { |
|
756 Append(faReadOnly); |
|
757 Remove(faReadWrite); |
|
758 } |
|
759 #endif // POSIX |
|
760 |
|
761 std::vector<FileAttribute>::iterator iterator = |
|
762 std::find(FAttributes.begin(), FAttributes.end(), Value); |
|
763 |
|
764 if (iterator != FAttributes.end()) { |
|
765 FAttributes.erase(iterator); |
|
766 WriteAttributes(); |
|
767 } |
|
768 } |
|
769 } |