src/jdk.jpackage/windows/native/libapplauncher/FilePath.cpp
branchJDK-8200758-branch
changeset 58994 b09ba68c6a19
parent 58993 b5e1baa9d2c3
child 58995 de1413ae214c
equal deleted inserted replaced
58993:b5e1baa9d2c3 58994:b09ba68c6a19
     1 /*
       
     2  * Copyright (c) 2014, 2019, 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 #include <ShellAPI.h>
       
    31 
       
    32 bool FilePath::FileExists(const TString FileName) {
       
    33     bool result = false;
       
    34     WIN32_FIND_DATA FindFileData;
       
    35     TString fileName = FixPathForPlatform(FileName);
       
    36     HANDLE handle = FindFirstFile(fileName.data(), &FindFileData);
       
    37 
       
    38     if (handle != INVALID_HANDLE_VALUE) {
       
    39         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
       
    40             result = true;
       
    41         }
       
    42         else {
       
    43             result = true;
       
    44         }
       
    45 
       
    46         FindClose(handle);
       
    47     }
       
    48     return result;
       
    49 }
       
    50 
       
    51 bool FilePath::DirectoryExists(const TString DirectoryName) {
       
    52     bool result = false;
       
    53     WIN32_FIND_DATA FindFileData;
       
    54     TString directoryName = FixPathForPlatform(DirectoryName);
       
    55     HANDLE handle = FindFirstFile(directoryName.data(), &FindFileData);
       
    56 
       
    57     if (handle != INVALID_HANDLE_VALUE) {
       
    58         if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
       
    59             result = true;
       
    60         }
       
    61 
       
    62         FindClose(handle);
       
    63     }
       
    64     return result;
       
    65 }
       
    66 
       
    67 std::string GetLastErrorAsString() {
       
    68     // Get the error message, if any.
       
    69     DWORD errorMessageID = ::GetLastError();
       
    70 
       
    71     if (errorMessageID == 0) {
       
    72         return "No error message has been recorded";
       
    73     }
       
    74 
       
    75     LPSTR messageBuffer = NULL;
       
    76     size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
       
    77             | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
       
    78             NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL,
       
    79             SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
       
    80 
       
    81     std::string message(messageBuffer, size);
       
    82 
       
    83     // Free the buffer.
       
    84     LocalFree(messageBuffer);
       
    85 
       
    86     return message;
       
    87 }
       
    88 
       
    89 bool FilePath::DeleteFile(const TString FileName) {
       
    90     bool result = false;
       
    91 
       
    92     if (FileExists(FileName) == true) {
       
    93         TString lFileName = FixPathForPlatform(FileName);
       
    94         FileAttributes attributes(lFileName);
       
    95 
       
    96         if (attributes.Contains(faReadOnly) == true) {
       
    97             attributes.Remove(faReadOnly);
       
    98         }
       
    99 
       
   100         result = ::DeleteFile(lFileName.data()) == TRUE;
       
   101     }
       
   102 
       
   103     return result;
       
   104 }
       
   105 
       
   106 bool FilePath::DeleteDirectory(const TString DirectoryName) {
       
   107     bool result = false;
       
   108 
       
   109     if (DirectoryExists(DirectoryName) == true) {
       
   110         SHFILEOPSTRUCTW fos = {0};
       
   111         TString directoryName = FixPathForPlatform(DirectoryName);
       
   112         DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2);
       
   113         if (lDirectoryName.GetData() == NULL) {
       
   114             return false;
       
   115         }
       
   116         memcpy(lDirectoryName.GetData(), directoryName.data(),
       
   117                 (directoryName.size() + 2) * sizeof(TCHAR));
       
   118         lDirectoryName[directoryName.size() + 1] = NULL;
       
   119         // Double null terminate for SHFileOperation.
       
   120 
       
   121         // Delete the folder and everything inside.
       
   122         fos.wFunc = FO_DELETE;
       
   123         fos.pFrom = lDirectoryName.GetData();
       
   124         fos.fFlags = FOF_NO_UI;
       
   125         result = SHFileOperation(&fos) == 0;
       
   126     }
       
   127 
       
   128     return result;
       
   129 }
       
   130 
       
   131 TString FilePath::IncludeTrailingSeparator(const TString value) {
       
   132     TString result = value;
       
   133 
       
   134     if (value.size() > 0) {
       
   135         TString::iterator i = result.end();
       
   136         i--;
       
   137 
       
   138         if (*i != TRAILING_PATHSEPARATOR) {
       
   139             result += TRAILING_PATHSEPARATOR;
       
   140         }
       
   141     }
       
   142 
       
   143     return result;
       
   144 }
       
   145 
       
   146 TString FilePath::IncludeTrailingSeparator(const char* value) {
       
   147     TString lvalue = PlatformString(value).toString();
       
   148     return IncludeTrailingSeparator(lvalue);
       
   149 }
       
   150 
       
   151 TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
       
   152     TString lvalue = PlatformString(value).toString();
       
   153     return IncludeTrailingSeparator(lvalue);
       
   154 }
       
   155 
       
   156 TString FilePath::ExtractFilePath(TString Path) {
       
   157     TString result;
       
   158     size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
       
   159     if (slash != TString::npos)
       
   160         result = Path.substr(0, slash);
       
   161     return result;
       
   162 }
       
   163 
       
   164 TString FilePath::ExtractFileExt(TString Path) {
       
   165     TString result;
       
   166     size_t dot = Path.find_last_of('.');
       
   167 
       
   168     if (dot != TString::npos) {
       
   169         result  = Path.substr(dot, Path.size() - dot);
       
   170     }
       
   171 
       
   172     return result;
       
   173 }
       
   174 
       
   175 TString FilePath::ExtractFileName(TString Path) {
       
   176     TString result;
       
   177 
       
   178     size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
       
   179     if (slash != TString::npos)
       
   180         result = Path.substr(slash + 1, Path.size() - slash - 1);
       
   181 
       
   182     return result;
       
   183 }
       
   184 
       
   185 TString FilePath::ChangeFileExt(TString Path, TString Extension) {
       
   186     TString result;
       
   187     size_t dot = Path.find_last_of('.');
       
   188 
       
   189     if (dot != TString::npos) {
       
   190         result = Path.substr(0, dot) + Extension;
       
   191     }
       
   192 
       
   193     if (result.empty() == true) {
       
   194         result = Path;
       
   195     }
       
   196 
       
   197     return result;
       
   198 }
       
   199 
       
   200 TString FilePath::FixPathForPlatform(TString Path) {
       
   201     TString result = Path;
       
   202     std::replace(result.begin(), result.end(),
       
   203             BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
       
   204     // The maximum path that does not require long path prefix. On Windows the
       
   205     // maximum path is 260 minus 1 (NUL) but for directories it is 260 minus
       
   206     // 12 minus 1 (to allow for the creation of a 8.3 file in the directory).
       
   207     const int maxPath = 247;
       
   208     if (result.length() > maxPath &&
       
   209         result.find(_T("\\\\?\\")) == TString::npos &&
       
   210         result.find(_T("\\\\?\\UNC")) == TString::npos) {
       
   211         const TString prefix(_T("\\\\"));
       
   212         if (!result.compare(0, prefix.size(), prefix)) {
       
   213             // UNC path, converting to UNC path in long notation
       
   214             result = _T("\\\\?\\UNC") + result.substr(1, result.length());
       
   215         } else {
       
   216             // converting to non-UNC path in long notation
       
   217             result = _T("\\\\?\\") + result;
       
   218         }
       
   219     }
       
   220     return result;
       
   221 }
       
   222 
       
   223 TString FilePath::FixPathSeparatorForPlatform(TString Path) {
       
   224     TString result = Path;
       
   225     std::replace(result.begin(), result.end(),
       
   226             BAD_PATH_SEPARATOR, PATH_SEPARATOR);
       
   227     return result;
       
   228 }
       
   229 
       
   230 TString FilePath::PathSeparator() {
       
   231     TString result;
       
   232     result = PATH_SEPARATOR;
       
   233     return result;
       
   234 }
       
   235 
       
   236 bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
       
   237     bool result = false;
       
   238 
       
   239     std::list<TString> paths;
       
   240     TString lpath = Path;
       
   241 
       
   242     while (lpath.empty() == false && DirectoryExists(lpath) == false) {
       
   243         paths.push_front(lpath);
       
   244         lpath = ExtractFilePath(lpath);
       
   245     }
       
   246 
       
   247     for (std::list<TString>::iterator iterator = paths.begin();
       
   248             iterator != paths.end(); iterator++) {
       
   249         lpath = *iterator;
       
   250 
       
   251         if (_wmkdir(lpath.data()) == 0) {
       
   252             result = true;
       
   253         } else {
       
   254             result = false;
       
   255             break;
       
   256         }
       
   257     }
       
   258 
       
   259     return result;
       
   260 }
       
   261 
       
   262 void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
       
   263 }
       
   264 
       
   265 #include <algorithm>
       
   266 
       
   267 FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
       
   268     FFileName = FileName;
       
   269     FFollowLink = FollowLink;
       
   270     ReadAttributes();
       
   271 }
       
   272 
       
   273 bool FileAttributes::WriteAttributes() {
       
   274     bool result = false;
       
   275 
       
   276     DWORD attributes = 0;
       
   277 
       
   278     for (std::vector<FileAttribute>::const_iterator iterator =
       
   279             FAttributes.begin();
       
   280         iterator != FAttributes.end(); iterator++) {
       
   281         switch (*iterator) {
       
   282             case faArchive: {
       
   283                 attributes = attributes & FILE_ATTRIBUTE_ARCHIVE;
       
   284                 break;
       
   285             }
       
   286             case faCompressed: {
       
   287                 attributes = attributes & FILE_ATTRIBUTE_COMPRESSED;
       
   288                 break;
       
   289             }
       
   290             case faDevice: {
       
   291                 attributes = attributes & FILE_ATTRIBUTE_DEVICE;
       
   292                 break;
       
   293             }
       
   294             case faDirectory: {
       
   295                 attributes = attributes & FILE_ATTRIBUTE_DIRECTORY;
       
   296                 break;
       
   297             }
       
   298             case faEncrypted: {
       
   299                 attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED;
       
   300                 break;
       
   301             }
       
   302             case faHidden: {
       
   303                 attributes = attributes & FILE_ATTRIBUTE_HIDDEN;
       
   304                 break;
       
   305             }
       
   306             case faNormal: {
       
   307                 attributes = attributes & FILE_ATTRIBUTE_NORMAL;
       
   308                 break;
       
   309             }
       
   310             case faNotContentIndexed: {
       
   311                 attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
       
   312                 break;
       
   313             }
       
   314             case faOffline: {
       
   315                 attributes = attributes & FILE_ATTRIBUTE_OFFLINE;
       
   316                 break;
       
   317             }
       
   318             case faSystem: {
       
   319                 attributes = attributes & FILE_ATTRIBUTE_SYSTEM;
       
   320                 break;
       
   321             }
       
   322             case faSymbolicLink: {
       
   323                 attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT;
       
   324                 break;
       
   325             }
       
   326             case faSparceFile: {
       
   327                 attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE;
       
   328                 break;
       
   329             }
       
   330             case faReadOnly: {
       
   331                 attributes = attributes & FILE_ATTRIBUTE_READONLY;
       
   332                 break;
       
   333             }
       
   334             case faTemporary: {
       
   335                 attributes = attributes & FILE_ATTRIBUTE_TEMPORARY;
       
   336                 break;
       
   337             }
       
   338             case faVirtual: {
       
   339                 attributes = attributes & FILE_ATTRIBUTE_VIRTUAL;
       
   340                 break;
       
   341             }
       
   342         }
       
   343     }
       
   344 
       
   345     if (::SetFileAttributes(FFileName.data(), attributes) != 0) {
       
   346         result = true;
       
   347     }
       
   348 
       
   349     return result;
       
   350 }
       
   351 
       
   352 #define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
       
   353 #define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
       
   354 #define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
       
   355 
       
   356 #define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
       
   357 #define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
       
   358 #define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
       
   359 
       
   360 #define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
       
   361 #define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
       
   362 #define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
       
   363 
       
   364 bool FileAttributes::ReadAttributes() {
       
   365     bool result = false;
       
   366 
       
   367     DWORD attributes = ::GetFileAttributes(FFileName.data());
       
   368 
       
   369     if (attributes != INVALID_FILE_ATTRIBUTES) {
       
   370         result = true;
       
   371 
       
   372         if (attributes | FILE_ATTRIBUTE_ARCHIVE) {
       
   373             FAttributes.push_back(faArchive);
       
   374         }
       
   375         if (attributes | FILE_ATTRIBUTE_COMPRESSED) {
       
   376             FAttributes.push_back(faCompressed);
       
   377         }
       
   378         if (attributes | FILE_ATTRIBUTE_DEVICE) {
       
   379             FAttributes.push_back(faDevice);
       
   380         }
       
   381         if (attributes | FILE_ATTRIBUTE_DIRECTORY) {
       
   382             FAttributes.push_back(faDirectory);
       
   383         }
       
   384         if (attributes | FILE_ATTRIBUTE_ENCRYPTED) {
       
   385             FAttributes.push_back(faEncrypted);
       
   386         }
       
   387         if (attributes | FILE_ATTRIBUTE_HIDDEN) {
       
   388             FAttributes.push_back(faHidden);
       
   389         }
       
   390         if (attributes | FILE_ATTRIBUTE_NORMAL) {
       
   391             FAttributes.push_back(faNormal);
       
   392         }
       
   393         if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) {
       
   394             FAttributes.push_back(faNotContentIndexed);
       
   395         }
       
   396         if (attributes | FILE_ATTRIBUTE_SYSTEM) {
       
   397             FAttributes.push_back(faSystem);
       
   398         }
       
   399         if (attributes | FILE_ATTRIBUTE_OFFLINE) {
       
   400             FAttributes.push_back(faOffline);
       
   401         }
       
   402         if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) {
       
   403             FAttributes.push_back(faSymbolicLink);
       
   404         }
       
   405         if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) {
       
   406             FAttributes.push_back(faSparceFile);
       
   407         }
       
   408         if (attributes | FILE_ATTRIBUTE_READONLY ) {
       
   409             FAttributes.push_back(faReadOnly);
       
   410         }
       
   411         if (attributes | FILE_ATTRIBUTE_TEMPORARY) {
       
   412             FAttributes.push_back(faTemporary);
       
   413         }
       
   414         if (attributes | FILE_ATTRIBUTE_VIRTUAL) {
       
   415             FAttributes.push_back(faVirtual);
       
   416         }
       
   417     }
       
   418 
       
   419     return result;
       
   420 }
       
   421 
       
   422 bool FileAttributes::Valid(const FileAttribute Value) {
       
   423     bool result = false;
       
   424 
       
   425     switch (Value) {
       
   426         case faHidden:
       
   427         case faReadOnly: {
       
   428             result = true;
       
   429             break;
       
   430         }
       
   431         default:
       
   432             break;
       
   433     }
       
   434 
       
   435     return result;
       
   436 }
       
   437 
       
   438 void FileAttributes::Append(FileAttribute Value) {
       
   439     if (Valid(Value) == true) {
       
   440         FAttributes.push_back(Value);
       
   441         WriteAttributes();
       
   442     }
       
   443 }
       
   444 
       
   445 bool FileAttributes::Contains(FileAttribute Value) {
       
   446     bool result = false;
       
   447 
       
   448     std::vector<FileAttribute>::const_iterator iterator =
       
   449             std::find(FAttributes.begin(), FAttributes.end(), Value);
       
   450 
       
   451     if (iterator != FAttributes.end()) {
       
   452         result = true;
       
   453     }
       
   454 
       
   455     return result;
       
   456 }
       
   457 
       
   458 void FileAttributes::Remove(FileAttribute Value) {
       
   459     if (Valid(Value) == true) {
       
   460         std::vector<FileAttribute>::iterator iterator =
       
   461             std::find(FAttributes.begin(), FAttributes.end(), Value);
       
   462 
       
   463         if (iterator != FAttributes.end()) {
       
   464             FAttributes.erase(iterator);
       
   465             WriteAttributes();
       
   466         }
       
   467     }
       
   468 }