4059 PAGE_READONLY, &old_status)) { |
4059 PAGE_READONLY, &old_status)) { |
4060 fatal("Could not enable polling page"); |
4060 fatal("Could not enable polling page"); |
4061 } |
4061 } |
4062 } |
4062 } |
4063 |
4063 |
|
4064 // combine the high and low DWORD into a ULONGLONG |
|
4065 static ULONGLONG make_double_word(DWORD high_word, DWORD low_word) { |
|
4066 ULONGLONG value = high_word; |
|
4067 value <<= sizeof(high_word) * 8; |
|
4068 value |= low_word; |
|
4069 return value; |
|
4070 } |
|
4071 |
|
4072 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat |
|
4073 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) { |
|
4074 ::memset((void*)sbuf, 0, sizeof(struct stat)); |
|
4075 sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow); |
|
4076 sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime, |
|
4077 file_data.ftLastWriteTime.dwLowDateTime); |
|
4078 sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime, |
|
4079 file_data.ftCreationTime.dwLowDateTime); |
|
4080 sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime, |
|
4081 file_data.ftLastAccessTime.dwLowDateTime); |
|
4082 if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
|
4083 sbuf->st_mode |= S_IFDIR; |
|
4084 } else { |
|
4085 sbuf->st_mode |= S_IFREG; |
|
4086 } |
|
4087 } |
|
4088 |
|
4089 // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c |
|
4090 // Creates an UNC path from a single byte path. Return buffer is |
|
4091 // allocated in C heap and needs to be freed by the caller. |
|
4092 // Returns NULL on error. |
|
4093 static wchar_t* create_unc_path(const char* path, errno_t &err) { |
|
4094 wchar_t* wpath = NULL; |
|
4095 size_t converted_chars = 0; |
|
4096 size_t path_len = strlen(path) + 1; // includes the terminating NULL |
|
4097 if (path[0] == '\\' && path[1] == '\\') { |
|
4098 if (path[2] == '?' && path[3] == '\\'){ |
|
4099 // if it already has a \\?\ don't do the prefix |
|
4100 wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal); |
|
4101 if (wpath != NULL) { |
|
4102 err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len); |
|
4103 } else { |
|
4104 err = ENOMEM; |
|
4105 } |
|
4106 } else { |
|
4107 // only UNC pathname includes double slashes here |
|
4108 wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal); |
|
4109 if (wpath != NULL) { |
|
4110 ::wcscpy(wpath, L"\\\\?\\UNC\0"); |
|
4111 err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); |
|
4112 } else { |
|
4113 err = ENOMEM; |
|
4114 } |
|
4115 } |
|
4116 } else { |
|
4117 wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal); |
|
4118 if (wpath != NULL) { |
|
4119 ::wcscpy(wpath, L"\\\\?\\\0"); |
|
4120 err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); |
|
4121 } else { |
|
4122 err = ENOMEM; |
|
4123 } |
|
4124 } |
|
4125 return wpath; |
|
4126 } |
|
4127 |
|
4128 static void destroy_unc_path(wchar_t* wpath) { |
|
4129 os::free(wpath); |
|
4130 } |
4064 |
4131 |
4065 int os::stat(const char *path, struct stat *sbuf) { |
4132 int os::stat(const char *path, struct stat *sbuf) { |
4066 char pathbuf[MAX_PATH]; |
4133 char* pathbuf = (char*)os::strdup(path, mtInternal); |
4067 if (strlen(path) > MAX_PATH - 1) { |
4134 if (pathbuf == NULL) { |
4068 errno = ENAMETOOLONG; |
4135 errno = ENOMEM; |
4069 return -1; |
4136 return -1; |
4070 } |
4137 } |
4071 os::native_path(strcpy(pathbuf, path)); |
4138 os::native_path(pathbuf); |
4072 int ret = ::stat(pathbuf, sbuf); |
4139 int ret; |
4073 if (sbuf != NULL && UseUTCFileTimestamp) { |
4140 WIN32_FILE_ATTRIBUTE_DATA file_data; |
4074 // Fix for 6539723. st_mtime returned from stat() is dependent on |
4141 // Not using stat() to avoid the problem described in JDK-6539723 |
4075 // the system timezone and so can return different values for the |
4142 if (strlen(path) < MAX_PATH) { |
4076 // same file if/when daylight savings time changes. This adjustment |
4143 BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data); |
4077 // makes sure the same timestamp is returned regardless of the TZ. |
4144 if (!bret) { |
4078 // |
4145 errno = ::GetLastError(); |
4079 // See: |
4146 ret = -1; |
4080 // http://msdn.microsoft.com/library/ |
4147 } |
4081 // default.asp?url=/library/en-us/sysinfo/base/ |
4148 else { |
4082 // time_zone_information_str.asp |
4149 file_attribute_data_to_stat(sbuf, file_data); |
4083 // and |
4150 ret = 0; |
4084 // http://msdn.microsoft.com/library/default.asp?url= |
4151 } |
4085 // /library/en-us/sysinfo/base/settimezoneinformation.asp |
4152 } else { |
4086 // |
4153 errno_t err = ERROR_SUCCESS; |
4087 // NOTE: there is a insidious bug here: If the timezone is changed |
4154 wchar_t* wpath = create_unc_path(pathbuf, err); |
4088 // after the call to stat() but before 'GetTimeZoneInformation()', then |
4155 if (err != ERROR_SUCCESS) { |
4089 // the adjustment we do here will be wrong and we'll return the wrong |
4156 if (wpath != NULL) { |
4090 // value (which will likely end up creating an invalid class data |
4157 destroy_unc_path(wpath); |
4091 // archive). Absent a better API for this, or some time zone locking |
4158 } |
4092 // mechanism, we'll have to live with this risk. |
4159 os::free(pathbuf); |
4093 TIME_ZONE_INFORMATION tz; |
4160 errno = err; |
4094 DWORD tzid = GetTimeZoneInformation(&tz); |
4161 return -1; |
4095 int daylightBias = |
4162 } |
4096 (tzid == TIME_ZONE_ID_DAYLIGHT) ? tz.DaylightBias : tz.StandardBias; |
4163 BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data); |
4097 sbuf->st_mtime += (tz.Bias + daylightBias) * 60; |
4164 if (!bret) { |
4098 } |
4165 errno = ::GetLastError(); |
|
4166 ret = -1; |
|
4167 } else { |
|
4168 file_attribute_data_to_stat(sbuf, file_data); |
|
4169 ret = 0; |
|
4170 } |
|
4171 destroy_unc_path(wpath); |
|
4172 } |
|
4173 os::free(pathbuf); |
4099 return ret; |
4174 return ret; |
4100 } |
4175 } |
4101 |
4176 |
4102 |
4177 |
4103 #define FT2INT64(ft) \ |
4178 #define FT2INT64(ft) \ |
4206 |
4281 |
4207 // This method is a slightly reworked copy of JDK's sysOpen |
4282 // This method is a slightly reworked copy of JDK's sysOpen |
4208 // from src/windows/hpi/src/sys_api_md.c |
4283 // from src/windows/hpi/src/sys_api_md.c |
4209 |
4284 |
4210 int os::open(const char *path, int oflag, int mode) { |
4285 int os::open(const char *path, int oflag, int mode) { |
4211 char pathbuf[MAX_PATH]; |
4286 char* pathbuf = (char*)os::strdup(path, mtInternal); |
4212 |
4287 if (pathbuf == NULL) { |
4213 if (strlen(path) > MAX_PATH - 1) { |
4288 errno = ENOMEM; |
4214 errno = ENAMETOOLONG; |
|
4215 return -1; |
4289 return -1; |
4216 } |
4290 } |
4217 os::native_path(strcpy(pathbuf, path)); |
4291 os::native_path(pathbuf); |
4218 return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); |
4292 int ret; |
|
4293 if (strlen(path) < MAX_PATH) { |
|
4294 ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); |
|
4295 } else { |
|
4296 errno_t err = ERROR_SUCCESS; |
|
4297 wchar_t* wpath = create_unc_path(pathbuf, err); |
|
4298 if (err != ERROR_SUCCESS) { |
|
4299 if (wpath != NULL) { |
|
4300 destroy_unc_path(wpath); |
|
4301 } |
|
4302 os::free(pathbuf); |
|
4303 errno = err; |
|
4304 return -1; |
|
4305 } |
|
4306 ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode); |
|
4307 if (ret == -1) { |
|
4308 errno = ::GetLastError(); |
|
4309 } |
|
4310 destroy_unc_path(wpath); |
|
4311 } |
|
4312 os::free(pathbuf); |
|
4313 return ret; |
4219 } |
4314 } |
4220 |
4315 |
4221 FILE* os::open(int fd, const char* mode) { |
4316 FILE* os::open(int fd, const char* mode) { |
4222 return ::_fdopen(fd, mode); |
4317 return ::_fdopen(fd, mode); |
4223 } |
4318 } |