< prev index next >

src/hotspot/os/windows/os_windows.cpp

Print this page
rev 55586 : 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 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);


< prev index next >