src/hotspot/os/windows/os_windows.cpp
changeset 48016 df39ee817323
parent 47903 7f22774a5f42
child 48105 8d15b1369c7a
equal deleted inserted replaced
48015:d5bb6637c785 48016:df39ee817323
  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 }