< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page




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;;




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 LPWSTR 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   // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4176   size_t buf_size = 1 + MAX2((size_t)3, strlen(path));
4177   char* buf = static_cast<char*>(os::malloc(buf_size, mtInternal));

4178   if (buf == NULL) {
4179     err = ENOMEM;
4180     return NULL;
4181   }
4182   memcpy(buf, path, buf_size);
4183   os::native_path(buf);
4184 
4185   // Get required buffer size to convert to Unicode
4186   int unicode_path_len = MultiByteToWideChar(CP_THREAD_ACP,
4187                                              MB_ERR_INVALID_CHARS,
4188                                              buf, -1,
4189                                              NULL, 0);
4190   if (unicode_path_len == 0) {
4191     os::free(buf);
4192     err = EINVAL;
4193     return NULL;
4194   }
4195 
4196   LPWSTR prefix;
4197   int prefix_off = 0;

4198   bool needs_fullpath = true;
4199 
4200   if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4201     prefix = L"\\\\?\\";
4202   } else if (buf[0] == '\\' && buf[1] == '\\') {
4203     if (buf[2] == '?' && buf[3] == '\\') {
4204       prefix = L"";
4205       needs_fullpath = false;
4206     } else {
4207       prefix = L"\\\\?\\UNC";
4208       prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4209     }
4210   } else {

4211     prefix = L"\\\\?\\";
4212   }


4213   size_t prefix_len = wcslen(prefix);
4214   LPWSTR result = NULL;


4215 
4216   LPWSTR unicode_path = static_cast<LPWSTR>(os::malloc(sizeof(WCHAR) * unicode_path_len, mtInternal));
4217   if (unicode_path == NULL) {
4218     err = ENOMEM;
4219   } else {
4220     // This call would be success because it is checked in above
4221     err = ERROR_SUCCESS;
4222     MultiByteToWideChar(CP_THREAD_ACP,
4223                         MB_ERR_INVALID_CHARS,
4224                         buf, -1,
4225                         unicode_path, unicode_path_len);
4226 
4227     size_t result_len = prefix_len + prefix_off + additional_space;
4228     if (needs_fullpath) {
4229       // Get required buffer size to convert to full path
4230       DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL);
4231       if (full_path_len == 0) {
4232         err = EINVAL;
4233       } else {
4234         size_t result_size = sizeof(WCHAR) * (result_len + full_path_len);
4235         result = static_cast<LPWSTR>(os::malloc(result_size, mtInternal));
4236         if (result == NULL) {
4237           err = ENOMEM;
4238         } else {
4239           // Copy prefix
4240           memcpy(result, prefix, sizeof(WCHAR) * prefix_len);
4241           // This call would be success because it is checked in above
4242           GetFullPathNameW(unicode_path, full_path_len, result + prefix_len - prefix_off, NULL);
4243         }
4244       }
4245     } else {
4246       size_t result_size = sizeof(WCHAR) * (result_len + unicode_path_len);
4247       result = static_cast<LPWSTR>(os::malloc(result_size, mtInternal));
4248       if (result == NULL) {
4249         err = ENOMEM;
4250       } else {
4251         // Copy prefix
4252         memcpy(result, prefix, sizeof(WCHAR) * prefix_len);
4253         // Copy unicode path
4254         memcpy(result + prefix_len - prefix_off, unicode_path, sizeof(WCHAR) * unicode_path_len);
4255       }
4256     }


4257 
4258     // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4259     result_len = wcslen(result);
4260 
4261     if (result[result_len - 1] == L'\\') {
4262       if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {
4263         result[result_len - 1] = L'\0';
4264       }
4265     }
4266   }

4267 
4268   os::free(unicode_path);
4269   os::free(buf);
4270 
4271   if (err != ERROR_SUCCESS) {
4272     os::free(result);
4273     result = NULL;
4274   }
4275 
4276   return result;
4277 }
4278 
4279 int os::stat(const char *path, struct stat *sbuf) {
4280   errno_t err;
4281   wchar_t* wide_path = wide_abs_unc_path(path, err);
4282 
4283   if (wide_path == NULL) {
4284     errno = err;
4285     return -1;
4286   }
4287 
4288   WIN32_FILE_ATTRIBUTE_DATA file_data;;


< prev index next >