< 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 static errno_t convert_to_unicode(char const* char_path, LPWSTR& unicode_path) {
4165   // Get required buffer size to convert to Unicode
4166   int unicode_path_len = MultiByteToWideChar(CP_THREAD_ACP,
4167                                              MB_ERR_INVALID_CHARS,
4168                                              char_path, -1,
4169                                              NULL, 0);
4170   if (unicode_path_len == 0) {
4171     return EINVAL;

4172   }
4173 
4174   size_t unicode_path_size = sizeof(WCHAR) * unicode_path_len;
4175   unicode_path = reinterpret_cast<LPWSTR>(os::malloc(unicode_path_size, mtInternal));
4176   if (unicode_path == NULL) {
4177     vm_exit_out_of_memory(unicode_path_size, OOM_MALLOC_ERROR, "convert_to_unicode");
4178   }
4179 
4180   int result = MultiByteToWideChar(CP_THREAD_ACP,
4181                                    MB_ERR_INVALID_CHARS,
4182                                    char_path, -1,
4183                                    unicode_path, unicode_path_len);
4184   assert(result == unicode_path_len, "length already checked above");
4185 
4186   return ERROR_SUCCESS;
4187 }
4188 
4189 static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR& full_path) {
4190   // Get required buffer size to convert to full path
4191   DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL);
4192   if (full_path_len == 0) {
4193     return EINVAL;
4194   }
4195 
4196   size_t full_path_size = sizeof(WCHAR) * full_path_len;
4197   full_path = reinterpret_cast<LPWSTR>(os::malloc(full_path_size, mtInternal));
4198   if (full_path == NULL) {
4199     vm_exit_out_of_memory(full_path_size, OOM_MALLOC_ERROR, "get_full_path");
4200   }
4201 
4202   DWORD result = GetFullPathNameW(unicode_path, full_path_len, full_path, NULL);
4203   assert(result == (full_path_len - 1), "length already checked above");
4204 
4205   return ERROR_SUCCESS;
4206 }
4207 
4208 static void set_path_prefix(char* buf, LPWSTR& prefix, int& prefix_off, bool& needs_fullpath) {
4209   prefix_off = 0;
4210   needs_fullpath = true;
4211 
4212   if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4213     prefix = L"\\\\?\\";
4214   } else if (buf[0] == '\\' && buf[1] == '\\') {
4215     if (buf[2] == '?' && buf[3] == '\\') {
4216       prefix = L"";
4217       needs_fullpath = false;
4218     } else {
4219       prefix = L"\\\\?\\UNC";
4220       prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4221     }
4222   } else {

4223     prefix = L"\\\\?\\";
4224   }
4225 }
4226 
4227 // Returns the given path as an absolute wide path in unc format. The returned path is NULL
4228 // on error (with err being set accordingly) and should be freed via os::free() otherwise.
4229 // additional_space is the number of additionally allocated wchars after the terminating L'\0'.
4230 // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for
4231 // short paths.
4232 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {
4233   if ((path == NULL) || (path[0] == '\0')) {
4234     err = ENOENT;
4235     return NULL;
4236   }
4237 
4238   // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4239   size_t buf_size = 1 + MAX2((size_t)3, strlen(path));
4240   char* buf = reinterpret_cast<char*>(os::malloc(buf_size, mtInternal));
4241   if (buf == NULL) {
4242     vm_exit_out_of_memory(buf_size, OOM_MALLOC_ERROR, "wide_abs_unc_path");
4243   }
4244   memcpy(buf, path, buf_size);
4245   os::native_path(buf);
4246 
4247   LPWSTR prefix;
4248   int prefix_off = 0;
4249   bool needs_fullpath = true;
4250   set_path_prefix(buf, prefix, prefix_off, needs_fullpath);
4251 
4252   LPWSTR unicode_path;
4253   err = convert_to_unicode(buf, unicode_path);
4254   os::free(buf);
4255   if (err != ERROR_SUCCESS) {
4256     return NULL;


4257   }
4258 
4259   LPWSTR converted_path = NULL;
4260   if (needs_fullpath) {
4261     err = get_full_path(unicode_path, converted_path);
4262   } else {
4263     converted_path = unicode_path;
4264   }
4265 
4266   LPWSTR result = NULL;
4267   if (converted_path != NULL) {
4268     size_t prefix_len = wcslen(prefix);
4269     size_t result_len = prefix_len - prefix_off + wcslen(converted_path) + additional_space + 1;
4270     result = reinterpret_cast<LPWSTR>(os::malloc(sizeof(WCHAR) * result_len, mtInternal));
4271     if (result == NULL) {
4272       vm_exit_out_of_memory(buf_size, OOM_MALLOC_ERROR, "wide_abs_unc_path");
4273     }
4274     _snwprintf(result, result_len, L"%s%s", prefix, &converted_path[prefix_off]);
4275 
4276     // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4277     result_len = wcslen(result);
4278     if ((result[result_len - 1] == L'\\') &&
4279         !(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {

4280       result[result_len - 1] = L'\0';
4281     }
4282   }


4283 
4284   if (converted_path != unicode_path) {
4285     os::free(converted_path);



4286   }
4287   os::free(unicode_path);
4288 
4289   return (wchar_t*)result; // LPWSTR and wchat_t* are the same type on Windows.
4290 }
4291 
4292 int os::stat(const char *path, struct stat *sbuf) {
4293   errno_t err;
4294   wchar_t* wide_path = wide_abs_unc_path(path, err);
4295 
4296   if (wide_path == NULL) {
4297     errno = err;
4298     return -1;
4299   }
4300 
4301   WIN32_FILE_ATTRIBUTE_DATA file_data;;
4302   BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
4303   os::free(wide_path);
4304 
4305   if (!bret) {
4306     errno = ::GetLastError();
4307     return -1;
4308   }
4309 


< prev index next >