modules/fxpackager/src/main/native/library/common/FilePath.cpp

Print this page




  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "FilePath.h"
  35 
  36 #include <algorithm>
  37 #include <list>
  38 




  39 #ifdef POSIX
  40 #include <sys/stat.h>
  41 #endif //POSIX
  42 
  43 
  44 bool FilePath::FileExists(const TString FileName) {
  45     bool result = false;
  46 #ifdef WINDOWS
  47     WIN32_FIND_DATA FindFileData;
  48     HANDLE handle = FindFirstFile(FileName.data(), &FindFileData);
  49 
  50     if (handle != INVALID_HANDLE_VALUE) {
  51         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
  52             result = true;
  53         }
  54         else {
  55             result = true;
  56         }
  57 
  58         FindClose(handle);


  75     HANDLE handle = FindFirstFile(DirectoryName.data(), &FindFileData);
  76 
  77     if (handle != INVALID_HANDLE_VALUE) {
  78         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
  79             result = true;
  80         }
  81 
  82         FindClose(handle);
  83     }
  84 #endif //WINDOWS
  85 #ifdef POSIX
  86     struct stat buf;
  87 
  88     if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) && (S_ISDIR(buf.st_mode) != 0)) {
  89         result = true;
  90     }
  91 #endif //POSIX
  92     return result;
  93 }
  94 






















  95 bool FilePath::DeleteFile(const TString FileName) {
  96     bool result = false;
  97 
  98     if (FileExists(FileName) == true) {
  99 #ifdef WINDOWS
 100         result = DeleteFile(FileName.data());







 101 #endif //WINDOWS
 102 #ifdef POSIX
 103         if (unlink(StringToFileSystemString(FileName)) == 0) {
 104             result = true;
 105         }
 106 #endif //POSIX
 107     }
 108 
 109     return result;
 110 }
 111 
 112 TString FilePath::IncludeTrailingSlash(const TString value) {


























 113     TString result = value;


 114     TString::iterator i = result.end();
 115     i--;
 116 
 117     if (*i != TRAILING_SLASH) {
 118         result += TRAILING_SLASH;

 119     }
 120 
 121     return result;
 122 }
 123 
 124 TString FilePath::IncludeTrailingSlash(const char* value) {
 125     TString lvalue = PlatformString(value).toString();
 126     return IncludeTrailingSlash(lvalue);
 127 }
 128 
 129 TString FilePath::IncludeTrailingSlash(const wchar_t* value) {
 130     TString lvalue = PlatformString(value).toString();
 131     return IncludeTrailingSlash(lvalue);
 132 }
 133 
 134 TString FilePath::ExtractFilePath(TString Path) {
 135 #ifdef WINDOWS
 136     TString result;
 137     size_t slash = Path.find_last_of(TRAILING_SLASH);
 138     if (slash != TString::npos)
 139         result = Path.substr(0, slash);
 140     return result;
 141 #endif //WINDOWS
 142 #ifdef POSIX
 143     return dirname(StringToFileSystemString(Path));
 144 #endif //POSIX
 145 }
 146 
 147 TString FilePath::ExtractFileExt(TString Path) {
 148     TString result;
 149     size_t dot = Path.find_last_of('.');
 150 
 151     if (dot != TString::npos) {
 152         result  = Path.substr(dot, Path.size() - dot);
 153     }
 154 
 155     return result;
 156 }
 157 
 158 TString FilePath::ExtractFileName(TString Path) {
 159 #ifdef WINDOWS
 160     TString result;
 161 
 162     size_t slash = Path.find_last_of(TRAILING_SLASH);
 163     if (slash != TString::npos)
 164         result = Path.substr(slash + 1, Path.size() - slash - 1);
 165 
 166     return result;
 167 #endif // WINDOWS
 168 #ifdef POSIX
 169     return basename(StringToFileSystemString(Path));
 170 #endif //POSIX
 171 }
 172 
 173 TString FilePath::ChangeFileExt(TString Path, TString Extension) {
 174     TString result;
 175     size_t dot = Path.find_last_of('.');
 176 
 177     if (dot != TString::npos) {
 178         result = Path.substr(0, dot) + Extension;
 179     }
 180 
 181     if (result.empty() == true) {
 182         result = Path;
 183     }
 184 
 185     return result;
 186 }
 187 






 188 TString FilePath::FixPathSeparatorForPlatform(TString Path) {
 189     TString result = Path;
 190     std::replace(result.begin(), result.end(), ' ', PATH_SEPARATOR);
 191     std::replace(result.begin(), result.end(), BAD_PATH_SEPARATOR, PATH_SEPARATOR);
 192     return result;
 193 }
 194 
 195 TString FilePath::PathSeparator() {
 196     TString result;
 197     result = PATH_SEPARATOR;
 198     return result;
 199 }
 200 
 201 bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
 202     bool result = false;
 203 
 204     std::list<TString> paths;
 205     TString lpath = Path;
 206 
 207     while (lpath.empty() == false && DirectoryExists(lpath) == false) {
 208         paths.push_front(lpath);
 209         lpath = ExtractFilePath(lpath);
 210     }


 217 #endif // WINDOWS
 218 #ifdef POSIX
 219         mode_t mode = S_IRWXU;
 220         if (!ownerOnly) {
 221             mode |= S_IRWXG | S_IROTH | S_IXOTH;
 222         }
 223         if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
 224 #endif //POSIX
 225             result = true;
 226         }
 227         else {
 228             result = false;
 229             break;
 230         }
 231     }
 232 
 233     return result;
 234 }
 235 
 236 void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
 237 
 238 #ifdef POSIX
 239     mode_t mode = S_IRWXU;
 240     if (!ownerOnly) {
 241         mode |= S_IRWXG | S_IROTH | S_IXOTH;
 242     }
 243     chmod(FileName.data(), mode);
 244 #endif // POSIX



























































































 245 



















































































































































































































































































 246 }


  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 
  33 
  34 #include "FilePath.h"
  35 
  36 #include <algorithm>
  37 #include <list>
  38 
  39 #ifdef WINDOWS
  40 #include <ShellAPI.h>
  41 #endif //WINDOWS
  42 
  43 #ifdef POSIX
  44 #include <sys/stat.h>
  45 #endif //POSIX
  46 
  47 
  48 bool FilePath::FileExists(const TString FileName) {
  49     bool result = false;
  50 #ifdef WINDOWS
  51     WIN32_FIND_DATA FindFileData;
  52     HANDLE handle = FindFirstFile(FileName.data(), &FindFileData);
  53 
  54     if (handle != INVALID_HANDLE_VALUE) {
  55         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
  56             result = true;
  57         }
  58         else {
  59             result = true;
  60         }
  61 
  62         FindClose(handle);


  79     HANDLE handle = FindFirstFile(DirectoryName.data(), &FindFileData);
  80 
  81     if (handle != INVALID_HANDLE_VALUE) {
  82         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
  83             result = true;
  84         }
  85 
  86         FindClose(handle);
  87     }
  88 #endif //WINDOWS
  89 #ifdef POSIX
  90     struct stat buf;
  91 
  92     if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) && (S_ISDIR(buf.st_mode) != 0)) {
  93         result = true;
  94     }
  95 #endif //POSIX
  96     return result;
  97 }
  98 
  99 #ifdef WINDOWS
 100 std::string GetLastErrorAsString() {
 101     //Get the error message, if any.
 102     DWORD errorMessageID = ::GetLastError();
 103 
 104     if (errorMessageID == 0) {
 105         return "No error message has been recorded";
 106     }
 107 
 108     LPSTR messageBuffer = NULL;
 109     size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 110                                  NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
 111 
 112     std::string message(messageBuffer, size);
 113 
 114     // Free the buffer.
 115     LocalFree(messageBuffer);
 116 
 117     return message;
 118 }
 119 #endif //WINDOWS
 120 
 121 bool FilePath::DeleteFile(const TString FileName) {
 122     bool result = false;
 123 
 124     if (FileExists(FileName) == true) {
 125 #ifdef WINDOWS
 126         TString lFileName = FileName;
 127         FileAttributes attributes(lFileName);
 128 
 129         if (attributes.Contains(faReadOnly) == true) {
 130             attributes.Remove(faReadOnly);
 131         }
 132 
 133         result = ::DeleteFile(lFileName.data()) == TRUE;
 134 #endif //WINDOWS
 135 #ifdef POSIX
 136         if (unlink(StringToFileSystemString(FileName)) == 0) {
 137             result = true;
 138         }
 139 #endif //POSIX
 140     }
 141 
 142     return result;
 143 }
 144 
 145 bool FilePath::DeleteDirectory(const TString DirectoryName) {
 146     bool result = false;
 147 
 148     if (DirectoryExists(DirectoryName) == true) {
 149 #ifdef WINDOWS
 150         SHFILEOPSTRUCTW fos = {0};
 151         DynamicBuffer<TCHAR> lDirectoryName(DirectoryName.size() + 2);
 152         memcpy(lDirectoryName.GetData(), DirectoryName.data(), (DirectoryName.size() + 2) * sizeof(TCHAR));
 153         lDirectoryName[DirectoryName.size() + 1] = NULL; // Double null terminate for SHFileOperation.
 154 
 155         // Delete the folder and everything inside.
 156         fos.wFunc = FO_DELETE;
 157         fos.pFrom = lDirectoryName.GetData();
 158         fos.fFlags = FOF_NO_UI;
 159         result = SHFileOperation(&fos) == 0;
 160 #endif //WINDOWS
 161 #ifdef POSIX
 162         if (unlink(StringToFileSystemString(DirectoryName)) == 0) {
 163             result = true;
 164         }
 165 #endif //POSIX
 166     }
 167 
 168     return result;
 169 }
 170 
 171 TString FilePath::IncludeTrailingSeparater(const TString value) {
 172     TString result = value;
 173 
 174     if (value.size() > 0) {
 175         TString::iterator i = result.end();
 176         i--;
 177 
 178         if (*i != TRAILING_PATHSEPARATOR) {
 179             result += TRAILING_PATHSEPARATOR;
 180         }
 181     }
 182 
 183     return result;
 184 }
 185 
 186 TString FilePath::IncludeTrailingSeparater(const char* value) {
 187     TString lvalue = PlatformString(value).toString();
 188     return IncludeTrailingSeparater(lvalue);
 189 }
 190 
 191 TString FilePath::IncludeTrailingSeparater(const wchar_t* value) {
 192     TString lvalue = PlatformString(value).toString();
 193     return IncludeTrailingSeparater(lvalue);
 194 }
 195 
 196 TString FilePath::ExtractFilePath(TString Path) {
 197 #ifdef WINDOWS
 198     TString result;
 199     size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
 200     if (slash != TString::npos)
 201         result = Path.substr(0, slash);
 202     return result;
 203 #endif //WINDOWS
 204 #ifdef POSIX
 205     return dirname(StringToFileSystemString(Path));
 206 #endif //POSIX
 207 }
 208 
 209 TString FilePath::ExtractFileExt(TString Path) {
 210     TString result;
 211     size_t dot = Path.find_last_of('.');
 212 
 213     if (dot != TString::npos) {
 214         result  = Path.substr(dot, Path.size() - dot);
 215     }
 216 
 217     return result;
 218 }
 219 
 220 TString FilePath::ExtractFileName(TString Path) {
 221 #ifdef WINDOWS
 222     TString result;
 223 
 224     size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
 225     if (slash != TString::npos)
 226         result = Path.substr(slash + 1, Path.size() - slash - 1);
 227 
 228     return result;
 229 #endif // WINDOWS
 230 #ifdef POSIX
 231     return basename(StringToFileSystemString(Path));
 232 #endif //POSIX
 233 }
 234 
 235 TString FilePath::ChangeFileExt(TString Path, TString Extension) {
 236     TString result;
 237     size_t dot = Path.find_last_of('.');
 238 
 239     if (dot != TString::npos) {
 240         result = Path.substr(0, dot) + Extension;
 241     }
 242 
 243     if (result.empty() == true) {
 244         result = Path;
 245     }
 246 
 247     return result;
 248 }
 249 
 250 TString FilePath::FixPathForPlatform(TString Path) {
 251     TString result = Path;
 252     std::replace(result.begin(), result.end(), BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
 253     return result;
 254 }
 255 
 256 TString FilePath::FixPathSeparatorForPlatform(TString Path) {
 257     TString result = Path;

 258     std::replace(result.begin(), result.end(), BAD_PATH_SEPARATOR, PATH_SEPARATOR);
 259     return result;
 260 }
 261 
 262 TString FilePath::PathSeparator() {
 263     TString result;
 264     result = PATH_SEPARATOR;
 265     return result;
 266 }
 267 
 268 bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
 269     bool result = false;
 270 
 271     std::list<TString> paths;
 272     TString lpath = Path;
 273 
 274     while (lpath.empty() == false && DirectoryExists(lpath) == false) {
 275         paths.push_front(lpath);
 276         lpath = ExtractFilePath(lpath);
 277     }


 284 #endif // WINDOWS
 285 #ifdef POSIX
 286         mode_t mode = S_IRWXU;
 287         if (!ownerOnly) {
 288             mode |= S_IRWXG | S_IROTH | S_IXOTH;
 289         }
 290         if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
 291 #endif //POSIX
 292             result = true;
 293         }
 294         else {
 295             result = false;
 296             break;
 297         }
 298     }
 299 
 300     return result;
 301 }
 302 
 303 void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {

 304 #ifdef POSIX
 305     mode_t mode = S_IRWXU;
 306     if (!ownerOnly) {
 307         mode |= S_IRWXG | S_IROTH | S_IXOTH;
 308     }
 309     chmod(FileName.data(), mode);
 310 #endif // POSIX
 311 }
 312 
 313 //--------------------------------------------------------------------------------------------------
 314 
 315 #include <algorithm>
 316 
 317 FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
 318     FFileName = FileName;
 319     FFollowLink = FollowLink;
 320     ReadAttributes();
 321 }
 322 
 323 bool FileAttributes::WriteAttributes() {
 324     bool result = false;
 325 
 326 #ifdef WINDOWS
 327     DWORD attributes = 0;
 328 
 329     for (std::vector<FileAttribute>::const_iterator iterator = FAttributes.begin();
 330          iterator != FAttributes.end(); iterator++) {
 331         switch (*iterator) {
 332             case faArchive: {
 333                 attributes = attributes & FILE_ATTRIBUTE_ARCHIVE;
 334                 break;
 335             }
 336             case faCompressed: {
 337                 attributes = attributes & FILE_ATTRIBUTE_COMPRESSED;
 338                 break;
 339             }
 340             case faDevice: {
 341                 attributes = attributes & FILE_ATTRIBUTE_DEVICE;
 342                 break;
 343             }
 344             case faDirectory: {
 345                 attributes = attributes & FILE_ATTRIBUTE_DIRECTORY;
 346                 break;
 347             }
 348             case faEncrypted: {
 349                 attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED;
 350                 break;
 351             }
 352             case faHidden: {
 353                 attributes = attributes & FILE_ATTRIBUTE_HIDDEN;
 354                 break;
 355             }
 356 //            case faIntegrityStream: {
 357 //                attributes = attributes & FILE_ATTRIBUTE_INTEGRITY_STREAM;
 358 //                break;
 359 //            }
 360             case faNormal: {
 361                 attributes = attributes & FILE_ATTRIBUTE_NORMAL;
 362                 break;
 363             }
 364             case faNotContentIndexed: {
 365                 attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
 366                 break;
 367             }
 368 //            case faNoScrubData: {
 369 //                attributes = attributes & FILE_ATTRIBUTE_NO_SCRUB_DATA;
 370 //                break;
 371 //            }
 372             case faOffline: {
 373                 attributes = attributes & FILE_ATTRIBUTE_OFFLINE;
 374                 break;
 375             }
 376             case faSystem: {
 377                 attributes = attributes & FILE_ATTRIBUTE_SYSTEM;
 378                 break;
 379             }
 380             case faSymbolicLink: {
 381                 attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT;
 382                 break;
 383             }
 384             case faSparceFile: {
 385                 attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE;
 386                 break;
 387             }
 388             case faReadOnly: {
 389                 attributes = attributes & FILE_ATTRIBUTE_READONLY;
 390                 break;
 391             }
 392             case faTemporary: {
 393                 attributes = attributes & FILE_ATTRIBUTE_TEMPORARY;
 394                 break;
 395             }
 396             case faVirtual: {
 397                 attributes = attributes & FILE_ATTRIBUTE_VIRTUAL;
 398                 break;
 399             }
 400         }
 401     }
 402 
 403     if (::SetFileAttributes(FFileName.data(), attributes) != 0) {
 404         result = true;
 405     }
 406 #endif // WINDOWS
 407 #ifdef POSIX
 408     mode_t attributes = 0;
 409 
 410     for (std::vector<FileAttribute>::const_iterator iterator = FAttributes.begin();
 411          iterator != FAttributes.end(); iterator++) {
 412         switch (*iterator) {
 413             case faBlockSpecial: {
 414                 attributes |= S_IFBLK;
 415                 break;
 416             }
 417             case faCharacterSpecial: {
 418                 attributes |= S_IFCHR;
 419                 break;
 420             }
 421             case faFIFOSpecial: {
 422                 attributes |= S_IFIFO;
 423                 break;
 424             }
 425             case faNormal: {
 426                 attributes |= S_IFREG;
 427                 break;
 428             }
 429             case faDirectory: {
 430                 attributes |= S_IFDIR;
 431                 break;
 432             }
 433             case faSymbolicLink: {
 434                 attributes |= S_IFLNK;
 435                 break;
 436             }
 437             case faSocket: {
 438                 attributes |= S_IFSOCK;
 439                 break;
 440             }
 441 
 442             // Owner
 443             case faReadOnly: {
 444                 attributes |= S_IRUSR;
 445                 break;
 446             }
 447             case  faWriteOnly: {
 448                 attributes |= S_IWUSR;
 449                 break;
 450             }
 451             case faReadWrite: {
 452                 attributes |= S_IRUSR;
 453                 attributes |= S_IWUSR;
 454                 break;
 455             }
 456             case faExecute: {
 457                 attributes |= S_IXUSR;
 458                 break;
 459             }
 460 
 461             // Group
 462             case faGroupReadOnly: {
 463                 attributes |= S_IRGRP;
 464                 break;
 465             }
 466             case  faGroupWriteOnly: {
 467                 attributes |= S_IWGRP;
 468                 break;
 469             }
 470             case faGroupReadWrite: {
 471                 attributes |= S_IRGRP;
 472                 attributes |= S_IWGRP;
 473                 break;
 474             }
 475             case faGroupExecute: {
 476                 attributes |= S_IXGRP;
 477                 break;
 478             }
 479 
 480             // Others
 481             case faOthersReadOnly: {
 482                 attributes |= S_IROTH;
 483                 break;
 484             }
 485             case  faOthersWriteOnly: {
 486                 attributes |= S_IWOTH;
 487                 break;
 488             }
 489             case faOthersReadWrite: {
 490                 attributes |= S_IROTH;
 491                 attributes |= S_IWOTH;
 492                 break;
 493             }
 494             case faOthersExecute: {
 495                 attributes |= S_IXOTH;
 496                 break;
 497             }
 498         }
 499     }
 500 
 501     if (chmod(FFileName.data(), attributes) == 0) {
 502         result = true;
 503     }
 504 #endif //POSIX
 505 
 506     return result;
 507 }
 508 
 509 #define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
 510 #define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
 511 #define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
 512 
 513 #define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
 514 #define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
 515 #define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
 516 
 517 #define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
 518 #define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
 519 #define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
 520 
 521 bool FileAttributes::ReadAttributes() {
 522     bool result = false;
 523 
 524 #ifdef WINDOWS
 525     DWORD attributes = ::GetFileAttributes(FFileName.data());
 526 
 527     if (attributes != INVALID_FILE_ATTRIBUTES) {
 528         result = true;
 529 
 530         if (attributes | FILE_ATTRIBUTE_ARCHIVE) { FAttributes.push_back(faArchive); }
 531         if (attributes | FILE_ATTRIBUTE_COMPRESSED) { FAttributes.push_back(faCompressed); }
 532         if (attributes | FILE_ATTRIBUTE_DEVICE) { FAttributes.push_back(faDevice); }
 533         if (attributes | FILE_ATTRIBUTE_DIRECTORY) { FAttributes.push_back(faDirectory); }
 534         if (attributes | FILE_ATTRIBUTE_ENCRYPTED) { FAttributes.push_back(faEncrypted); }
 535         if (attributes | FILE_ATTRIBUTE_HIDDEN) { FAttributes.push_back(faHidden); }
 536         //if (attributes | FILE_ATTRIBUTE_INTEGRITY_STREAM) { FAttributes.push_back(faIntegrityStream); }
 537         if (attributes | FILE_ATTRIBUTE_NORMAL) { FAttributes.push_back(faNormal); }
 538         if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) { FAttributes.push_back(faNotContentIndexed); }
 539         //if (attributes | FILE_ATTRIBUTE_NO_SCRUB_DATA) { FAttributes.push_back(faNoScrubData); }
 540         if (attributes | FILE_ATTRIBUTE_SYSTEM) { FAttributes.push_back(faSystem); }
 541         if (attributes | FILE_ATTRIBUTE_OFFLINE) { FAttributes.push_back(faOffline); }
 542         if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) { FAttributes.push_back(faSymbolicLink); }
 543         if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) { FAttributes.push_back(faSparceFile); }
 544         if (attributes | FILE_ATTRIBUTE_READONLY ) { FAttributes.push_back(faReadOnly); }
 545         if (attributes | FILE_ATTRIBUTE_TEMPORARY) { FAttributes.push_back(faTemporary); }
 546         if (attributes | FILE_ATTRIBUTE_VIRTUAL) { FAttributes.push_back(faVirtual); }
 547     }
 548 #endif // WINDOWS
 549 #ifdef POSIX
 550     struct stat status;
 551 
 552     if (stat(StringToFileSystemString(FFileName), &status) == 0) {
 553         result = true;
 554 
 555         if (S_ISBLK(status.st_mode) != 0) { FAttributes.push_back(faBlockSpecial); }
 556         if (S_ISCHR(status.st_mode) != 0) { FAttributes.push_back(faCharacterSpecial); }
 557         if (S_ISFIFO(status.st_mode) != 0) { FAttributes.push_back(faFIFOSpecial); }
 558         if (S_ISREG(status.st_mode) != 0) { FAttributes.push_back(faNormal); }
 559         if (S_ISDIR(status.st_mode) != 0) { FAttributes.push_back(faDirectory); }
 560         if (S_ISLNK(status.st_mode) != 0) { FAttributes.push_back(faSymbolicLink); }
 561         if (S_ISSOCK(status.st_mode) != 0) { FAttributes.push_back(faSocket); }
 562 
 563         // Owner
 564         if (S_ISRUSR(status.st_mode) != 0) {
 565             if (S_ISWUSR(status.st_mode) != 0) { FAttributes.push_back(faReadWrite); }
 566             else { FAttributes.push_back(faReadOnly); }
 567         }
 568         else if (S_ISWUSR(status.st_mode) != 0) { FAttributes.push_back(faWriteOnly); }
 569 
 570         if (S_ISXUSR(status.st_mode) != 0) { FAttributes.push_back(faExecute); }
 571 
 572         // Group
 573         if (S_ISRGRP(status.st_mode) != 0) {
 574             if (S_ISWGRP(status.st_mode) != 0) { FAttributes.push_back(faGroupReadWrite); }
 575             else { FAttributes.push_back(faGroupReadOnly); }
 576         }
 577         else if (S_ISWGRP(status.st_mode) != 0) { FAttributes.push_back(faGroupWriteOnly); }
 578 
 579         if (S_ISXGRP(status.st_mode) != 0) { FAttributes.push_back(faGroupExecute); }
 580 
 581 
 582         // Others
 583         if (S_ISROTH(status.st_mode) != 0) {
 584             if (S_ISWOTH(status.st_mode) != 0) { FAttributes.push_back(faOthersReadWrite); }
 585             else { FAttributes.push_back(faOthersReadOnly); }
 586         }
 587         else if (S_ISWOTH(status.st_mode) != 0) { FAttributes.push_back(faOthersWriteOnly); }
 588 
 589         if (S_ISXOTH(status.st_mode) != 0) { FAttributes.push_back(faOthersExecute); }
 590 
 591         if (FFileName.size() > 0 && FFileName[0] == '.') {
 592             FAttributes.push_back(faHidden);
 593         }
 594     }
 595 #endif //POSIX
 596 
 597     return result;
 598 }
 599 
 600 bool FileAttributes::Valid(const FileAttribute Value) {
 601     bool result = false;
 602 
 603     switch (Value) {
 604 #ifdef WINDOWS
 605         case faHidden:
 606 #endif // WINDOWS
 607 #ifdef POSIX
 608         case faReadWrite:
 609         case faWriteOnly:
 610         case faExecute:
 611 
 612         case faGroupReadWrite:
 613         case faGroupWriteOnly:
 614         case faGroupReadOnly:
 615         case faGroupExecute:
 616 
 617         case faOthersReadWrite:
 618         case faOthersWriteOnly:
 619         case faOthersReadOnly:
 620         case faOthersExecute:
 621 #endif //POSIX
 622 
 623         case faReadOnly: {
 624             result = true;
 625             break;
 626         }
 627     }
 628 
 629     return result;
 630 }
 631 
 632 void FileAttributes::Append(FileAttribute Value) {
 633     if (Valid(Value) == true) {
 634 #ifdef POSIX
 635         if ((Value == faReadOnly && Contains(faWriteOnly) == true) ||
 636             (Value == faWriteOnly && Contains(faReadOnly) == true)) {
 637             Value = faReadWrite;
 638         }
 639 #endif //POSIX
 640 
 641         FAttributes.push_back(Value);
 642         WriteAttributes();
 643     }
 644 }
 645 
 646 bool FileAttributes::Contains(FileAttribute Value) {
 647     bool result = false;
 648 
 649     std::vector<FileAttribute>::const_iterator iterator = std::find(FAttributes.begin(), FAttributes.end(), Value);
 650 
 651     if (iterator != FAttributes.end()) {
 652         result = true;
 653     }
 654 
 655     return result;
 656 }
 657 
 658 void FileAttributes::Remove(FileAttribute Value) {
 659     if (Valid(Value) == true) {
 660 #ifdef POSIX
 661         if (Value == faReadOnly && Contains(faReadWrite) == true) {
 662             Append(faWriteOnly);
 663             Remove(faReadWrite);
 664         }
 665         else if (Value == faWriteOnly && Contains(faReadWrite) == true) {
 666             Append(faReadOnly);
 667             Remove(faReadWrite);
 668         }
 669 #endif //POSIX
 670 
 671         std::vector<FileAttribute>::iterator iterator = std::find(FAttributes.begin(), FAttributes.end(), Value);
 672 
 673         if (iterator != FAttributes.end()) {
 674             FAttributes.erase(iterator);
 675             WriteAttributes();
 676         }
 677     }
 678 }