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 er 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 static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {
4286 if (path == NULL) {
4287 err = ENOENT;
4288 return NULL;
4289 }
4290
4291 size_t path_len = strlen(path);
4292 // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4293 char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal);
4294 wchar_t* result = NULL;
4295
4296 if (buf == NULL) {
4297 err = ENOMEM;
4298 } else {
4299 memcpy(buf, path, path_len + 1);
4300 os::native_path(buf);
4301
4302 wchar_t* prefix;
4303 int prefix_off = 0;
4304 bool is_abs = true;
4305 bool needs_fullpath = true;
4306
4307 if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {
4308 prefix = L"\\\\?\\";
4309 } else if (buf[0] == '\\' && buf[1] == '\\') {
4310 assert(buf[2] != '\\');
4311
4312 if (buf[2] == '?' && buf[3] == '\\') {
4313 prefix = L"";
4314 needs_fullpath = false;
4315 } else {
4316 prefix = L"\\\\?\\UNC";
4317 prefix_off = 1; // Overwrite the first char with the prefix.
4318 }
4319 } else {
4320 is_abs = false;
4321 prefix = L"\\\\?\\";
4322 }
4323
4324 size_t buf_len = strlen(buf);
4325 size_t prefix_len = wcslen(prefix);
4326 size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN;
4327 size_t result_size = prefix_len + full_path_size - prefix_off;
4328 result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal);
4329
4330 if (result == NULL) {
4331 err = ENOMEM;
4332 } else {
4333 size_t converted_chars;
4334 wchar_t* path_start = result + prefix_len - prefix_off;
4335 err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len);
4336
4337 if ((err == ERROR_SUCCESS) && needs_fullpath) {
4338 wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal);
4339
4340 if (tmp == NULL) {
4341 err = ENOMEM;
4342 } else {
4343 if (!_wfullpath(tmp, path_start, full_path_size)) {
4344 err = ENOENT;
4345 } else {
4346 ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t));
4347 }
4348
4349 os::free(tmp);
4350 }
4351 }
4352
4353 memcpy(result, prefix, sizeof(wchar_t) * prefix_len);
4354
4355 // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4356 size_t result_len = wcslen(result);
4357
4358 if (result[result_len - 1] == L'\\') {
4359 if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {
4360 result[result_len - 1] = L'\0';
4361 }
4362 }
4363 }
4364 }
4365
4366 os::free(buf);
4367
4368 if (err != ERROR_SUCCESS) {
4369 os::free(result);
4370 result = NULL;
4371 }
4372
4373 return result;
4374 }
4375
4376 int os::stat(const char *path, struct stat *sbuf) {
4377 errno_t err;
4378 wchar_t* wide_path = wide_abs_unc_path(path, err);
4379
4380 if (wide_path == NULL) {
4381 errno = err;
4382 return -1;
4383 }
4384
4385 WIN32_FILE_ATTRIBUTE_DATA file_data;;
4386 BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);
4387 os::free(wide_path);
4388
4389 if (!bret) {
4390 errno = ::GetLastError();
4391 return -1;
4392 }
4393
4394 file_attribute_data_to_stat(sbuf, file_data);
4395 return 0;
4396 }
4397
4398 static HANDLE create_read_only_file_handle(const char* file) {
4399 errno_t err;
4400 wchar_t* wide_path = wide_abs_unc_path(file, err);
4401
4402 if (wide_path == NULL) {
4403 errno = err;
4404 return INVALID_HANDLE_VALUE;
4405 }
4406
4407 HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ,
4408 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4409 os::free(wide_path);
4410
4411 return handle;
4412 }
4413
4414 bool os::same_files(const char* file1, const char* file2) {
4415
4416 if (file1 == NULL && file2 == NULL) {
4417 return true;
4418 }
4419
4420 if (file1 == NULL || file2 == NULL) {
4421 return false;
4422 }
4423
4424 if (strcmp(file1, file2) == 0) {
4425 return true;
4426 }
4427
4428 HANDLE handle1 = create_read_only_file_handle(file1);
4429 HANDLE handle2 = create_read_only_file_handle(file2);
4430 bool result = false;
4439 if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
4440 fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
4441 fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {
4442 result = true;
4443 }
4444 }
4445 }
4446
4447 //free the handles
4448 if (handle1 != INVALID_HANDLE_VALUE) {
4449 ::CloseHandle(handle1);
4450 }
4451
4452 if (handle2 != INVALID_HANDLE_VALUE) {
4453 ::CloseHandle(handle2);
4454 }
4455
4456 return result;
4457 }
4458
4459 #define FT2INT64(ft) \
4460 ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
4461
4462
4463 // current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
4464 // are used by JVM M&M and JVMTI to get user+sys or user CPU time
4465 // of a thread.
4466 //
4467 // current_thread_cpu_time() and thread_cpu_time(Thread*) returns
4468 // the fast estimate available on the platform.
4469
4470 // current_thread_cpu_time() is not optimized for Windows yet
4471 jlong os::current_thread_cpu_time() {
4472 // return user + sys since the cost is the same
4473 return os::thread_cpu_time(Thread::current(), true /* user+sys */);
4474 }
4475
4476 jlong os::thread_cpu_time(Thread* thread) {
4477 // consistent with what current_thread_cpu_time() returns.
4478 return os::thread_cpu_time(thread, true /* user+sys */);
4543 // returns 100%), so we'd have to deal with that as well.
4544 //
4545 // b) Sample the "fake" answer using a sampling thread and store
4546 // the answer in a global variable. The call to loadavg would
4547 // just return the value of the global, avoiding the slow query.
4548 //
4549 // c) Sample a better answer using exponential decay to smooth the
4550 // value. This is basically the algorithm used by UNIX kernels.
4551 //
4552 // Note that sampling thread starvation could affect both (b) and (c).
4553 int os::loadavg(double loadavg[], int nelem) {
4554 return -1;
4555 }
4556
4557
4558 // DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()
4559 bool os::dont_yield() {
4560 return DontYieldALot;
4561 }
4562
4563 int os::open(const char *path, int oflag, int mode) {
4564 errno_t err;
4565 wchar_t* wide_path = wide_abs_unc_path(path, err);
4566
4567 if (wide_path == NULL) {
4568 errno = err;
4569 return -1;
4570 }
4571 int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode);
4572 os::free(wide_path);
4573
4574 if (fd == -1) {
4575 errno = ::GetLastError();
4576 }
4577
4578 return fd;
4579 }
4580
4581 FILE* os::open(int fd, const char* mode) {
4582 return ::_fdopen(fd, mode);
4583 }
4584
4585 // Is a (classpath) directory empty?
4586 bool os::dir_is_empty(const char* path) {
4587 errno_t err;
4588 wchar_t* wide_path = wide_abs_unc_path(path, err, 2);
4589
4590 if (wide_path == NULL) {
4591 errno = err;
4592 return false;
4593 }
4594
4595 // Make sure we end with "\\*"
4596 if (wide_path[wcslen(wide_path) - 1] == L'\\') {
4597 wcscat(wide_path, L"*");
4598 } else {
4599 wcscat(wide_path, L"\\*");
4600 }
4601
4602 WIN32_FIND_DATAW fd;
4603 HANDLE f = ::FindFirstFileW(wide_path, &fd);
4604 os::free(wide_path);
4605 bool is_empty = true;
4606
4607 if (f != INVALID_HANDLE_VALUE) {
4608 while (is_empty && ::FindNextFileW(f, &fd)) {
4609 // An empty directory contains only the current directory file
4610 // and the previous directory file.
4611 if ((wcscmp(fd.cFileName, L".") != 0) &&
4612 (wcscmp(fd.cFileName, L"..") != 0)) {
4613 is_empty = false;
4614 }
4615 }
4616 FindClose(f);
4617 } else {
4618 errno = ::GetLastError();
4619 }
4620
4621 return is_empty;
4622 }
4623
4624 // create binary file, rewriting existing file if required
4625 int os::create_binary_file(const char* path, bool rewrite_existing) {
4626 int oflags = _O_CREAT | _O_WRONLY | _O_BINARY;
4627 if (!rewrite_existing) {
4628 oflags |= _O_EXCL;
4629 }
4630 return ::open(path, oflags, _S_IREAD | _S_IWRITE);
4631 }
4632
4633 // return current position of file pointer
4634 jlong os::current_file_offset(int fd) {
4635 return (jlong)::_lseeki64(fd, (__int64)0L, SEEK_CUR);
4636 }
4637
4638 // move file pointer to the specified offset
4639 jlong os::seek_to_file_offset(int fd, jlong offset) {
4640 return (jlong)::_lseeki64(fd, (__int64)offset, SEEK_SET);
|