< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page
rev 55820 : 8191521: handle long relative path specified in -Xbootclasspath/a on windows
Reviewed-by:


4262   return value;
4263 }
4264 
4265 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat
4266 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) {
4267   ::memset((void*)sbuf, 0, sizeof(struct stat));
4268   sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow);
4269   sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime,
4270                                   file_data.ftLastWriteTime.dwLowDateTime);
4271   sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime,
4272                                   file_data.ftCreationTime.dwLowDateTime);
4273   sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime,
4274                                   file_data.ftLastAccessTime.dwLowDateTime);
4275   if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
4276     sbuf->st_mode |= S_IFDIR;
4277   } else {
4278     sbuf->st_mode |= S_IFREG;
4279   }
4280 }
4281 
4282 // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c
4283 // Creates an UNC path from a single byte path. Return buffer is
4284 // allocated in C heap and needs to be freed by the caller.
4285 // Returns NULL on error.
4286 static wchar_t* create_unc_path(const char* path, errno_t &err) {
4287   wchar_t* wpath = NULL;
4288   size_t converted_chars = 0;
4289   size_t path_len = strlen(path) + 1; // includes the terminating NULL
4290   if (path[0] == '\\' && path[1] == '\\') {
4291     if (path[2] == '?' && path[3] == '\\'){
4292       // if it already has a \\?\ don't do the prefix
4293       wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal);
4294       if (wpath != NULL) {
4295         err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len);
4296       } else {


4297         err = ENOMEM;
4298       }
4299     } else {
4300       // only UNC pathname includes double slashes here
4301       wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal);
4302       if (wpath != NULL) {
4303         ::wcscpy(wpath, L"\\\\?\\UNC\0");
4304         err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len);











4305       } else {
4306         err = ENOMEM;
4307       }
4308     }
4309   } else {
4310     wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal);
4311     if (wpath != NULL) {
4312       ::wcscpy(wpath, L"\\\\?\\\0");
4313       err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len);








4314     } else {








4315       err = ENOMEM;








4316     }
4317   }
4318   return wpath;
4319 }
4320 
4321 static void destroy_unc_path(wchar_t* wpath) {
4322   os::free(wpath);
4323 }
4324 
4325 int os::stat(const char *path, struct stat *sbuf) {
4326   char* pathbuf = (char*)os::strdup(path, mtInternal);
4327   if (pathbuf == NULL) {
4328     errno = ENOMEM;
4329     return -1;

4330   }
4331   os::native_path(pathbuf);
4332   int ret;
4333   WIN32_FILE_ATTRIBUTE_DATA file_data;
4334   // Not using stat() to avoid the problem described in JDK-6539723
4335   if (strlen(path) < MAX_PATH) {
4336     BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data);
4337     if (!bret) {
4338       errno = ::GetLastError();
4339       ret = -1;
4340     }
4341     else {
4342       file_attribute_data_to_stat(sbuf, file_data);
4343       ret = 0;
4344     }
4345   } else {
4346     errno_t err = ERROR_SUCCESS;
4347     wchar_t* wpath = create_unc_path(pathbuf, err);

4348     if (err != ERROR_SUCCESS) {
4349       if (wpath != NULL) {
4350         destroy_unc_path(wpath);
4351       }
4352       os::free(pathbuf);








4353       errno = err;
4354       return -1;
4355     }
4356     BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data);




4357     if (!bret) {
4358       errno = ::GetLastError();
4359       ret = -1;
4360     } else {
4361       file_attribute_data_to_stat(sbuf, file_data);
4362       ret = 0;
4363     }
4364     destroy_unc_path(wpath);
4365   }
4366   os::free(pathbuf);
4367   return ret;

4368 }
4369 
4370 static HANDLE create_read_only_file_handle(const char* file) {
4371   if (file == NULL) {
4372     return INVALID_HANDLE_VALUE;
4373   }
4374 
4375   char* nativepath = (char*)os::strdup(file, mtInternal);
4376   if (nativepath == NULL) {
4377     errno = ENOMEM;
4378     return INVALID_HANDLE_VALUE;
4379   }
4380   os::native_path(nativepath);
4381 
4382   size_t len = strlen(nativepath);
4383   HANDLE handle = INVALID_HANDLE_VALUE;
4384 
4385   if (len < MAX_PATH) {
4386     handle = ::CreateFile(nativepath, 0, FILE_SHARE_READ,
4387                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4388   } else {
4389     errno_t err = ERROR_SUCCESS;
4390     wchar_t* wfile = create_unc_path(nativepath, err);
4391     if (err != ERROR_SUCCESS) {
4392       if (wfile != NULL) {
4393         destroy_unc_path(wfile);
4394       }
4395       os::free(nativepath);
4396       return INVALID_HANDLE_VALUE;
4397     }
4398     handle = ::CreateFileW(wfile, 0, FILE_SHARE_READ,
4399                            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4400     destroy_unc_path(wfile);
4401   }
4402 
4403   os::free(nativepath);
4404   return handle;
4405 }
4406 
4407 bool os::same_files(const char* file1, const char* file2) {
4408 
4409   if (file1 == NULL && file2 == NULL) {
4410     return true;
4411   }
4412 
4413   if (file1 == NULL || file2 == NULL) {
4414     return false;
4415   }
4416 
4417   if (strcmp(file1, file2) == 0) {
4418     return true;
4419   }
4420 
4421   HANDLE handle1 = create_read_only_file_handle(file1);
4422   HANDLE handle2 = create_read_only_file_handle(file2);
4423   bool result = false;


4432       if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
4433         fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
4434         fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {
4435         result = true;
4436       }
4437     }
4438   }
4439 
4440   //free the handles
4441   if (handle1 != INVALID_HANDLE_VALUE) {
4442     ::CloseHandle(handle1);
4443   }
4444 
4445   if (handle2 != INVALID_HANDLE_VALUE) {
4446     ::CloseHandle(handle2);
4447   }
4448 
4449   return result;
4450 }
4451 
4452 
4453 #define FT2INT64(ft) \
4454   ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
4455 
4456 
4457 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
4458 // are used by JVM M&M and JVMTI to get user+sys or user CPU time
4459 // of a thread.
4460 //
4461 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns
4462 // the fast estimate available on the platform.
4463 
4464 // current_thread_cpu_time() is not optimized for Windows yet
4465 jlong os::current_thread_cpu_time() {
4466   // return user + sys since the cost is the same
4467   return os::thread_cpu_time(Thread::current(), true /* user+sys */);
4468 }
4469 
4470 jlong os::thread_cpu_time(Thread* thread) {
4471   // consistent with what current_thread_cpu_time() returns.
4472   return os::thread_cpu_time(thread, true /* user+sys */);


4537 //    returns 100%), so we'd have to deal with that as well.
4538 //
4539 // b) Sample the "fake" answer using a sampling thread and store
4540 //    the answer in a global variable.  The call to loadavg would
4541 //    just return the value of the global, avoiding the slow query.
4542 //
4543 // c) Sample a better answer using exponential decay to smooth the
4544 //    value.  This is basically the algorithm used by UNIX kernels.
4545 //
4546 // Note that sampling thread starvation could affect both (b) and (c).
4547 int os::loadavg(double loadavg[], int nelem) {
4548   return -1;
4549 }
4550 
4551 
4552 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()
4553 bool os::dont_yield() {
4554   return DontYieldALot;
4555 }
4556 
4557 // This method is a slightly reworked copy of JDK's sysOpen
4558 // from src/windows/hpi/src/sys_api_md.c
4559 
4560 int os::open(const char *path, int oflag, int mode) {
4561   char* pathbuf = (char*)os::strdup(path, mtInternal);
4562   if (pathbuf == NULL) {
4563     errno = ENOMEM;
4564     return -1;
4565   }
4566   os::native_path(pathbuf);
4567   int ret;
4568   if (strlen(path) < MAX_PATH) {
4569     ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
4570   } else {
4571     errno_t err = ERROR_SUCCESS;
4572     wchar_t* wpath = create_unc_path(pathbuf, err);
4573     if (err != ERROR_SUCCESS) {
4574       if (wpath != NULL) {
4575         destroy_unc_path(wpath);
4576       }
4577       os::free(pathbuf);
4578       errno = err;
4579       return -1;
4580     }
4581     ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode);
4582     if (ret == -1) {


4583       errno = ::GetLastError();
4584     }
4585     destroy_unc_path(wpath);
4586   }
4587   os::free(pathbuf);
4588   return ret;
4589 }
4590 
4591 FILE* os::open(int fd, const char* mode) {
4592   return ::_fdopen(fd, mode);
4593 }
4594 
4595 // Is a (classpath) directory empty?
4596 bool os::dir_is_empty(const char* path) {
4597   char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal);
4598   if (search_path == NULL) {
4599     errno = ENOMEM;
4600     return false;
4601   }
4602   strcpy(search_path, path);
4603   os::native_path(search_path);
4604   // Append "*", or possibly "\\*", to path
4605   if (search_path[1] == ':' &&
4606        (search_path[2] == '\0' ||
4607          (search_path[2] == '\\' && search_path[3] == '\0'))) {
4608     // No '\\' needed for cases like "Z:" or "Z:\"
4609     strcat(search_path, "*");
4610   }
4611   else {
4612     strcat(search_path, "\\*");
4613   }
4614   errno_t err = ERROR_SUCCESS;
4615   wchar_t* wpath = create_unc_path(search_path, err);
4616   if (err != ERROR_SUCCESS) {
4617     if (wpath != NULL) {
4618       destroy_unc_path(wpath);
4619     }
4620     os::free(search_path);
4621     errno = err;
4622     return false;
4623   }








4624   WIN32_FIND_DATAW fd;
4625   HANDLE f = ::FindFirstFileW(wpath, &fd);
4626   destroy_unc_path(wpath);
4627   bool is_empty = true;

4628   if (f != INVALID_HANDLE_VALUE) {
4629     while (is_empty && ::FindNextFileW(f, &fd)) {
4630       // An empty directory contains only the current directory file
4631       // and the previous directory file.
4632       if ((wcscmp(fd.cFileName, L".") != 0) &&
4633           (wcscmp(fd.cFileName, L"..") != 0)) {
4634         is_empty = false;
4635       }
4636     }
4637     FindClose(f);


4638   }
4639   os::free(search_path);
4640   return is_empty;
4641 }
4642 
4643 // create binary file, rewriting existing file if required
4644 int os::create_binary_file(const char* path, bool rewrite_existing) {
4645   int oflags = _O_CREAT | _O_WRONLY | _O_BINARY;
4646   if (!rewrite_existing) {
4647     oflags |= _O_EXCL;
4648   }
4649   return ::open(path, oflags, _S_IREAD | _S_IWRITE);
4650 }
4651 
4652 // return current position of file pointer
4653 jlong os::current_file_offset(int fd) {
4654   return (jlong)::_lseeki64(fd, (__int64)0L, SEEK_CUR);
4655 }
4656 
4657 // move file pointer to the specified offset
4658 jlong os::seek_to_file_offset(int fd, jlong offset) {
4659   return (jlong)::_lseeki64(fd, (__int64)offset, SEEK_SET);




4262   return value;
4263 }
4264 
4265 // Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat
4266 static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) {
4267   ::memset((void*)sbuf, 0, sizeof(struct stat));
4268   sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow);
4269   sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime,
4270                                   file_data.ftLastWriteTime.dwLowDateTime);
4271   sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime,
4272                                   file_data.ftCreationTime.dwLowDateTime);
4273   sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime,
4274                                   file_data.ftLastAccessTime.dwLowDateTime);
4275   if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
4276     sbuf->st_mode |= S_IFDIR;
4277   } else {
4278     sbuf->st_mode |= S_IFREG;
4279   }
4280 }
4281 
4282 // Returns the given path as an absolute wide path in unc format. The returned path is NULL
4283 // on error (with err being set accordingly) and should be freed via os::free() otherwise.
4284 // additional_space is the number of additionally allocated wchars after the terminating L'\0'.
4285 // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for
4286 // short paths.
4287 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {
4288   if (path == NULL) {
4289     err = ENOENT;
4290     return NULL;
4291   }
4292 
4293   size_t path_len = strlen(path);
4294   // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4295   char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal);
4296   wchar_t* result = NULL;
4297 
4298   if (buf == NULL) {
4299     err = ENOMEM;

4300   } else {
4301     memcpy(buf, path, path_len + 1);
4302     os::native_path(buf);
4303 
4304     wchar_t* prefix;
4305     int prefix_off = 0;
4306     bool is_abs = true;
4307     bool needs_fullpath = true;
4308 
4309     if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4310       prefix = L"\\\\?\\";
4311     } else if (buf[0] == '\\' && buf[1] == '\\') {
4312       assert(buf[2] != '\\');
4313 
4314       if (buf[2] == '?' && buf[3] == '\\') {
4315         prefix = L"";
4316         needs_fullpath = false;
4317       } else {
4318         prefix = L"\\\\?\\UNC";
4319         prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4320       }
4321     } else {
4322       is_abs = false;
4323       prefix = L"\\\\?\\";
4324     }
4325 
4326     size_t buf_len = strlen(buf);
4327     size_t prefix_len = wcslen(prefix);
4328     size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN;
4329     size_t result_size = prefix_len + full_path_size - prefix_off;
4330     result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal);
4331 
4332     if (result == NULL) {
4333       err = ENOMEM;
4334     } else {
4335       size_t converted_chars;
4336       wchar_t* path_start = result + prefix_len - prefix_off;
4337       err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len);
4338 
4339       if ((err == ERROR_SUCCESS) && needs_fullpath) {
4340         wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal);
4341 
4342         if (tmp == NULL) {
4343           err = ENOMEM;
4344         } else {
4345           if (!_wfullpath(tmp, path_start, full_path_size)) {
4346             err = ENOENT;
4347           } else {
4348             ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t));
4349           }
4350 
4351           os::free(tmp);
4352         }
4353       }


4354 
4355       memcpy(result, prefix, sizeof(wchar_t) * prefix_len);


4356 
4357       // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4358       size_t result_len = wcslen(result);
4359 
4360       if (result[result_len - 1] == L'\\') {
4361         if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {
4362           result[result_len - 1] = L'\0';
4363         }









4364       }



4365     }
4366   }
4367 
4368   os::free(buf);
4369 
4370   if (err != ERROR_SUCCESS) {
4371     os::free(result);
4372     result = NULL;
4373   }
4374 
4375   return result;
4376 }
4377 
4378 int os::stat(const char *path, struct stat *sbuf) {
4379   errno_t err;
4380   wchar_t* wide_path = wide_abs_unc_path(path, err);
4381 
4382   if (wide_path == NULL) {
4383     errno = err;
4384     return -1;
4385   }
4386 
4387   WIN32_FILE_ATTRIBUTE_DATA file_data;;
4388   BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
4389   os::free(wide_path);
4390 
4391   if (!bret) {
4392     errno = ::GetLastError();
4393     return -1;





4394   }
4395 
4396   file_attribute_data_to_stat(sbuf, file_data);
4397   return 0;
4398 }
4399 
4400 static HANDLE create_read_only_file_handle(const char* file) {
4401   errno_t err;
4402   wchar_t* wide_path = wide_abs_unc_path(file, err);

4403 
4404   if (wide_path == NULL) {
4405     errno = err;

4406     return INVALID_HANDLE_VALUE;
4407   }




4408 
4409   HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ,













4410                                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4411   os::free(wide_path);

4412 

4413   return handle;
4414 }
4415 
4416 bool os::same_files(const char* file1, const char* file2) {
4417 
4418   if (file1 == NULL && file2 == NULL) {
4419     return true;
4420   }
4421 
4422   if (file1 == NULL || file2 == NULL) {
4423     return false;
4424   }
4425 
4426   if (strcmp(file1, file2) == 0) {
4427     return true;
4428   }
4429 
4430   HANDLE handle1 = create_read_only_file_handle(file1);
4431   HANDLE handle2 = create_read_only_file_handle(file2);
4432   bool result = false;


4441       if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
4442         fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
4443         fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {
4444         result = true;
4445       }
4446     }
4447   }
4448 
4449   //free the handles
4450   if (handle1 != INVALID_HANDLE_VALUE) {
4451     ::CloseHandle(handle1);
4452   }
4453 
4454   if (handle2 != INVALID_HANDLE_VALUE) {
4455     ::CloseHandle(handle2);
4456   }
4457 
4458   return result;
4459 }
4460 

4461 #define FT2INT64(ft) \
4462   ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
4463 
4464 
4465 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
4466 // are used by JVM M&M and JVMTI to get user+sys or user CPU time
4467 // of a thread.
4468 //
4469 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns
4470 // the fast estimate available on the platform.
4471 
4472 // current_thread_cpu_time() is not optimized for Windows yet
4473 jlong os::current_thread_cpu_time() {
4474   // return user + sys since the cost is the same
4475   return os::thread_cpu_time(Thread::current(), true /* user+sys */);
4476 }
4477 
4478 jlong os::thread_cpu_time(Thread* thread) {
4479   // consistent with what current_thread_cpu_time() returns.
4480   return os::thread_cpu_time(thread, true /* user+sys */);


4545 //    returns 100%), so we'd have to deal with that as well.
4546 //
4547 // b) Sample the "fake" answer using a sampling thread and store
4548 //    the answer in a global variable.  The call to loadavg would
4549 //    just return the value of the global, avoiding the slow query.
4550 //
4551 // c) Sample a better answer using exponential decay to smooth the
4552 //    value.  This is basically the algorithm used by UNIX kernels.
4553 //
4554 // Note that sampling thread starvation could affect both (b) and (c).
4555 int os::loadavg(double loadavg[], int nelem) {
4556   return -1;
4557 }
4558 
4559 
4560 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()
4561 bool os::dont_yield() {
4562   return DontYieldALot;
4563 }
4564 



4565 int os::open(const char *path, int oflag, int mode) {
4566   errno_t err;
4567   wchar_t* wide_path = wide_abs_unc_path(path, err);
4568 
4569   if (wide_path == NULL) {













4570     errno = err;
4571     return -1;
4572   }
4573   int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode);
4574   os::free(wide_path);
4575 
4576   if (fd == -1) {
4577     errno = ::GetLastError();
4578   }
4579 
4580   return fd;


4581 }
4582 
4583 FILE* os::open(int fd, const char* mode) {
4584   return ::_fdopen(fd, mode);
4585 }
4586 
4587 // Is a (classpath) directory empty?
4588 bool os::dir_is_empty(const char* path) {
4589   errno_t err;
4590   wchar_t* wide_path = wide_abs_unc_path(path, err, 2);
4591 
4592   if (wide_path == NULL) {




















4593     errno = err;
4594     return false;
4595   }
4596 
4597   // Make sure we end with "\\*"
4598   if (wide_path[wcslen(wide_path) - 1] == L'\\') {
4599     wcscat(wide_path, L"*");
4600   } else {
4601     wcscat(wide_path, L"\\*");
4602   }
4603 
4604   WIN32_FIND_DATAW fd;
4605   HANDLE f = ::FindFirstFileW(wide_path, &fd);
4606   os::free(wide_path);
4607   bool is_empty = true;
4608 
4609   if (f != INVALID_HANDLE_VALUE) {
4610     while (is_empty && ::FindNextFileW(f, &fd)) {
4611       // An empty directory contains only the current directory file
4612       // and the previous directory file.
4613       if ((wcscmp(fd.cFileName, L".") != 0) &&
4614           (wcscmp(fd.cFileName, L"..") != 0)) {
4615         is_empty = false;
4616       }
4617     }
4618     FindClose(f);
4619   } else {
4620     errno = ::GetLastError();
4621   }
4622 
4623   return is_empty;
4624 }
4625 
4626 // create binary file, rewriting existing file if required
4627 int os::create_binary_file(const char* path, bool rewrite_existing) {
4628   int oflags = _O_CREAT | _O_WRONLY | _O_BINARY;
4629   if (!rewrite_existing) {
4630     oflags |= _O_EXCL;
4631   }
4632   return ::open(path, oflags, _S_IREAD | _S_IWRITE);
4633 }
4634 
4635 // return current position of file pointer
4636 jlong os::current_file_offset(int fd) {
4637   return (jlong)::_lseeki64(fd, (__int64)0L, SEEK_CUR);
4638 }
4639 
4640 // move file pointer to the specified offset
4641 jlong os::seek_to_file_offset(int fd, jlong offset) {
4642   return (jlong)::_lseeki64(fd, (__int64)offset, SEEK_SET);


< prev index next >