src/jdk.jpackager/share/native/library/common/FilePath.cpp
branchJDK-8200758-branch
changeset 57017 1b08af362a30
parent 56993 3629eb24e9ac
equal deleted inserted replaced
57016:f63f13da91c0 57017:1b08af362a30
       
     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 }