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