< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page




4144   return value;
4145 }
4146 
4147 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat
4148 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) {
4149   ::memset((void*)sbuf, 0, sizeof(struct stat));
4150   sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow);
4151   sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime,
4152                                   file_data.ftLastWriteTime.dwLowDateTime);
4153   sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime,
4154                                   file_data.ftCreationTime.dwLowDateTime);
4155   sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime,
4156                                   file_data.ftLastAccessTime.dwLowDateTime);
4157   if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
4158     sbuf->st_mode |= S_IFDIR;
4159   } else {
4160     sbuf->st_mode |= S_IFREG;
4161   }
4162 }
4163 




















4164 // Returns the given path as an absolute wide path in unc format. The returned path is NULL
4165 // on error (with err being set accordingly) and should be freed via os::free() otherwise.
4166 // additional_space is the number of additionally allocated wchars after the terminating L'\0'.
4167 // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for
4168 // short paths.
4169 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {
4170   if ((path == NULL) || (path[0] == '\0')) {
4171     err = ENOENT;
4172     return NULL;
4173   }
4174 
4175   size_t path_len = strlen(path);
4176   // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4177   char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal);
4178   wchar_t* result = NULL;
4179 
4180   if (buf == NULL) {
4181     err = ENOMEM;
4182   } else {
4183     memcpy(buf, path, path_len + 1);
4184     os::native_path(buf);
4185 
4186     wchar_t* prefix;




4187     int prefix_off = 0;
4188     bool is_abs = true;
4189     bool needs_fullpath = true;
4190 
4191     if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4192       prefix = L"\\\\?\\";
4193     } else if (buf[0] == '\\' && buf[1] == '\\') {
4194       if (buf[2] == '?' && buf[3] == '\\') {
4195         prefix = L"";
4196         needs_fullpath = false;
4197       } else {
4198         prefix = L"\\\\?\\UNC";
4199         prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4200       }
4201     } else {
4202       is_abs = false;
4203       prefix = L"\\\\?\\";
4204     }
4205 
4206     size_t buf_len = strlen(buf);
4207     size_t prefix_len = wcslen(prefix);
4208     size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN;
4209     size_t result_size = prefix_len + full_path_size - prefix_off;
4210     result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal);
4211 
4212     if (result == NULL) {
4213       err = ENOMEM;
4214     } else {
4215       size_t converted_chars;
4216       wchar_t* path_start = result + prefix_len - prefix_off;
4217       err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len);
4218 
4219       if ((err == ERROR_SUCCESS) && needs_fullpath) {
4220         wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal);
4221 
4222         if (tmp == NULL) {
4223           err = ENOMEM;
4224         } else {
4225           if (!_wfullpath(tmp, path_start, full_path_size)) {
4226             err = ENOENT;
4227           } else {
4228             ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t));

4229           }
4230 
4231           os::free(tmp);
4232         }



4233       }
4234 
4235       memcpy(result, prefix, sizeof(wchar_t) * prefix_len);
4236 
4237       // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4238       size_t result_len = wcslen(result);
4239 
4240       if (result[result_len - 1] == L'\\') {
4241         if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {
4242           result[result_len - 1] = L'\0';
4243         }
4244       }
4245     }
4246   }
4247 
4248   os::free(buf);
4249 
4250   if (err != ERROR_SUCCESS) {
4251     os::free(result);
4252     result = NULL;
4253   }
4254 
4255   return result;

4256 }
4257 
4258 int os::stat(const char *path, struct stat *sbuf) {
4259   errno_t err;
4260   wchar_t* wide_path = wide_abs_unc_path(path, err);
4261 
4262   if (wide_path == NULL) {
4263     errno = err;
4264     return -1;
4265   }
4266 
4267   WIN32_FILE_ATTRIBUTE_DATA file_data;;
4268   BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
4269   os::free(wide_path);
4270 
4271   if (!bret) {
4272     errno = ::GetLastError();
4273     return -1;
4274   }
4275 




4144   return value;
4145 }
4146 
4147 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat
4148 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) {
4149   ::memset((void*)sbuf, 0, sizeof(struct stat));
4150   sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow);
4151   sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime,
4152                                   file_data.ftLastWriteTime.dwLowDateTime);
4153   sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime,
4154                                   file_data.ftCreationTime.dwLowDateTime);
4155   sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime,
4156                                   file_data.ftLastAccessTime.dwLowDateTime);
4157   if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
4158     sbuf->st_mode |= S_IFDIR;
4159   } else {
4160     sbuf->st_mode |= S_IFREG;
4161   }
4162 }
4163 
4164 #define TO_UNICODE(mbs, wcs, wcs_len, err) \
4165   wcs_len = MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS,        \
4166                                 mbs, -1, NULL, 0);                          \
4167   if (wcs_len == 0) {                                                       \
4168     err = EINVAL;                                                           \
4169     return NULL;                                                            \
4170   }                                                                         \
4171   wcs = reinterpret_cast<LPWSTR>(alloca(sizeof(WCHAR) * unicode_path_len)); \
4172   MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS,                  \
4173                       mbs, -1, wcs, wcs_len);
4174 
4175 #define TO_FULL_PATH(rp, fp, fp_len, err) \
4176   fp_len = GetFullPathNameW(rp, 0, NULL, NULL);                  \
4177   if (fp_len == 0) {                                             \
4178     err = EINVAL;                                                \
4179     return NULL;                                                 \
4180   }                                                              \
4181   fp = reinterpret_cast<LPWSTR>(alloca(sizeof(WCHAR) * fp_len)); \
4182   GetFullPathNameW(rp, fp_len, fp, NULL);
4183 
4184 // Returns the given path as an absolute wide path in unc format. The returned path is NULL
4185 // on error (with err being set accordingly) and should be freed via os::free() otherwise.
4186 // additional_space is the number of additionally allocated wchars after the terminating L'\0'.
4187 // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for
4188 // short paths.
4189 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {
4190   if ((path == NULL) || (path[0] == '\0')) {
4191     err = ENOENT;
4192     return NULL;
4193   }
4194 

4195   // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4196   size_t buf_size = 1 + MAX2((size_t)3, strlen(path));
4197   char* buf = reinterpret_cast<char*>(alloca(buf_size));
4198   memcpy(buf, path, buf_size);




4199   os::native_path(buf);
4200 
4201   LPWSTR unicode_path;
4202   DWORD unicode_path_len;
4203   TO_UNICODE(buf, unicode_path, unicode_path_len, err)
4204 
4205   LPWSTR prefix;
4206   int prefix_off = 0;

4207   bool needs_fullpath = true;
4208 
4209   if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4210     prefix = L"\\\\?\\";
4211   } else if (buf[0] == '\\' && buf[1] == '\\') {
4212     if (buf[2] == '?' && buf[3] == '\\') {
4213       prefix = L"";
4214       needs_fullpath = false;
4215     } else {
4216       prefix = L"\\\\?\\UNC";
4217       prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4218     }
4219   } else {

4220     prefix = L"\\\\?\\";
4221   }
4222 
4223   LPWSTR converted_path;
4224   DWORD converted_path_len;
4225   if (needs_fullpath) {
4226     TO_FULL_PATH(unicode_path, converted_path, converted_path_len, err)

















4227   } else {
4228     converted_path = unicode_path;
4229     converted_path_len = unicode_path_len;
4230   }
4231 
4232   size_t prefix_len = wcslen(prefix);
4233   size_t result_len = prefix_len - prefix_off + converted_path_len + additional_space + 1;
4234   LPWSTR result = reinterpret_cast<LPWSTR>(os::malloc(sizeof(WCHAR) * result_len, mtInternal));
4235   if (result == NULL) {
4236     vm_exit_out_of_memory(buf_size, OOM_MALLOC_ERROR, "wide_abs_unc_path");
4237   }
4238   _snwprintf(result, result_len, L"%s%s", prefix, &converted_path[prefix_off]);

4239 
4240   // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4241   result_len = wcslen(result);

4242   if (result[result_len - 1] == L'\\') {
4243     if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {
4244       result[result_len - 1] = L'\0';
4245     }
4246   }









4247 
4248   err = ERROR_SUCCESS;
4249   return static_cast<wchar_t*>(result); // LPWSTR and wchat_t* are the same type on Windows.
4250 }
4251 
4252 int os::stat(const char *path, struct stat *sbuf) {
4253   errno_t err;
4254   wchar_t* wide_path = wide_abs_unc_path(path, err);
4255 
4256   if (wide_path == NULL) {
4257     errno = err;
4258     return -1;
4259   }
4260 
4261   WIN32_FILE_ATTRIBUTE_DATA file_data;;
4262   BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
4263   os::free(wide_path);
4264 
4265   if (!bret) {
4266     errno = ::GetLastError();
4267     return -1;
4268   }
4269 


< prev index next >