@@ -4159,128 +4159,137 @@ static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_
4159
4159
}
4160
4160
}
4161
4161
4162
- // The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c
4163
- // Creates an UNC path from a single byte path. Return buffer is
4164
- // allocated in C heap and needs to be freed by the caller.
4165
- // Returns NULL on error.
4166
- static wchar_t * create_unc_path (const char * path, errno_t &err) {
4167
- wchar_t * wpath = NULL ;
4168
- size_t converted_chars = 0 ;
4169
- size_t path_len = strlen (path) + 1 ; // includes the terminating NULL
4170
- if (path[0 ] == ' \\ ' && path[1 ] == ' \\ ' ) {
4171
- if (path[2 ] == ' ?' && path[3 ] == ' \\ ' ){
4172
- // if it already has a \\?\ don't do the prefix
4173
- wpath = (wchar_t *)os::malloc (path_len * sizeof (wchar_t ), mtInternal);
4174
- if (wpath != NULL ) {
4175
- err = ::mbstowcs_s (&converted_chars, wpath, path_len, path, path_len);
4162
+ // Returns the given path as an absolute wide path in unc format. The returned path is NULL
4163
+ // on error (with err being set accordingly) and should be freed via os::free() otherwise.
4164
+ // additional_space is the number of additionally allocated wchars after the terminating L'\0'.
4165
+ // This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for
4166
+ // short paths.
4167
+ static wchar_t * wide_abs_unc_path (char const * path, errno_t & err, int additional_space = 0 ) {
4168
+ if ((path == NULL ) || (path[0 ] == ' \0 ' )) {
4169
+ err = ENOENT;
4170
+ return NULL ;
4171
+ }
4172
+
4173
+ size_t path_len = strlen (path);
4174
+ // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.
4175
+ char * buf = (char *) os::malloc (1 + MAX2 ((size_t ) 3 , path_len), mtInternal);
4176
+ wchar_t * result = NULL ;
4177
+
4178
+ if (buf == NULL ) {
4179
+ err = ENOMEM;
4180
+ } else {
4181
+ memcpy (buf, path, path_len + 1 );
4182
+ os::native_path (buf);
4183
+
4184
+ wchar_t * prefix;
4185
+ int prefix_off = 0 ;
4186
+ bool is_abs = true ;
4187
+ bool needs_fullpath = true ;
4188
+
4189
+ if (::isalpha (buf[0 ]) && !::IsDBCSLeadByte (buf[0 ]) && buf[1 ] == ' :' && buf[2 ] == ' \\ ' ) {
4190
+ prefix = L" \\\\ ?\\ " ;
4191
+ } else if (buf[0 ] == ' \\ ' && buf[1 ] == ' \\ ' ) {
4192
+ assert (buf[2 ] != ' \\ ' );
4193
+
4194
+ if (buf[2 ] == ' ?' && buf[3 ] == ' \\ ' ) {
4195
+ prefix = L" " ;
4196
+ needs_fullpath = false ;
4176
4197
} else {
4177
- err = ENOMEM;
4198
+ prefix = L" \\\\ ?\\ UNC" ;
4199
+ prefix_off = 1 ; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path
4178
4200
}
4179
4201
} else {
4180
- // only UNC pathname includes double slashes here
4181
- wpath = (wchar_t *)os::malloc ((path_len + 7 ) * sizeof (wchar_t ), mtInternal);
4182
- if (wpath != NULL ) {
4183
- ::wcscpy (wpath, L" \\\\ ?\\ UNC\0 " );
4184
- err = ::mbstowcs_s (&converted_chars, &wpath[7 ], path_len, path, path_len);
4185
- } else {
4186
- err = ENOMEM;
4187
- }
4202
+ is_abs = false ;
4203
+ prefix = L" \\\\ ?\\ " ;
4188
4204
}
4189
- } else {
4190
- wpath = (wchar_t *)os::malloc ((path_len + 4 ) * sizeof (wchar_t ), mtInternal);
4191
- if (wpath != NULL ) {
4192
- ::wcscpy (wpath, L" \\\\ ?\\\0 " );
4193
- err = ::mbstowcs_s (&converted_chars, &wpath[4 ], path_len, path, path_len);
4194
- } else {
4205
+
4206
+ size_t buf_len = strlen (buf);
4207
+ size_t prefix_len = wcslen (prefix);
4208
+ size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN;
4209
+ size_t result_size = prefix_len + full_path_size - prefix_off;
4210
+ result = (wchar_t *) os::malloc (sizeof (wchar_t ) * (additional_space + result_size), mtInternal);
4211
+
4212
+ if (result == NULL ) {
4195
4213
err = ENOMEM;
4214
+ } else {
4215
+ size_t converted_chars;
4216
+ wchar_t * path_start = result + prefix_len - prefix_off;
4217
+ err = ::mbstowcs_s (&converted_chars, path_start, buf_len + 1 , buf, buf_len);
4218
+
4219
+ if ((err == ERROR_SUCCESS) && needs_fullpath) {
4220
+ wchar_t * tmp = (wchar_t *) os::malloc (sizeof (wchar_t ) * full_path_size, mtInternal);
4221
+
4222
+ if (tmp == NULL ) {
4223
+ err = ENOMEM;
4224
+ } else {
4225
+ if (!_wfullpath (tmp, path_start, full_path_size)) {
4226
+ err = ENOENT;
4227
+ } else {
4228
+ ::memcpy (path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t ));
4229
+ }
4230
+
4231
+ os::free (tmp);
4232
+ }
4233
+ }
4234
+
4235
+ memcpy (result, prefix, sizeof (wchar_t ) * prefix_len);
4236
+
4237
+ // Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)
4238
+ size_t result_len = wcslen (result);
4239
+
4240
+ if (result[result_len - 1 ] == L' \\ ' ) {
4241
+ if (!(::iswalpha (result[4 ]) && result[5 ] == L' :' && result_len == 7 )) {
4242
+ result[result_len - 1 ] = L' \0 ' ;
4243
+ }
4244
+ }
4196
4245
}
4197
4246
}
4198
- return wpath;
4199
- }
4200
4247
4201
- static void destroy_unc_path (wchar_t * wpath) {
4202
- os::free (wpath);
4248
+ os::free (buf);
4249
+
4250
+ if (err != ERROR_SUCCESS) {
4251
+ os::free (result);
4252
+ result = NULL ;
4253
+ }
4254
+
4255
+ return result;
4203
4256
}
4204
4257
4205
4258
int os::stat (const char *path, struct stat *sbuf) {
4206
- char * pathbuf = (char *)os::strdup (path, mtInternal);
4207
- if (pathbuf == NULL ) {
4208
- errno = ENOMEM;
4259
+ errno_t err;
4260
+ wchar_t * wide_path = wide_abs_unc_path (path, err);
4261
+
4262
+ if (wide_path == NULL ) {
4263
+ errno = err;
4209
4264
return -1 ;
4210
4265
}
4211
- os::native_path (pathbuf);
4212
- int ret;
4213
- WIN32_FILE_ATTRIBUTE_DATA file_data;
4214
- // Not using stat() to avoid the problem described in JDK-6539723
4215
- if (strlen (path) < MAX_PATH) {
4216
- BOOL bret = ::GetFileAttributesExA (pathbuf, GetFileExInfoStandard, &file_data);
4217
- if (!bret) {
4218
- errno = ::GetLastError ();
4219
- ret = -1 ;
4220
- }
4221
- else {
4222
- file_attribute_data_to_stat (sbuf, file_data);
4223
- ret = 0 ;
4224
- }
4225
- } else {
4226
- errno_t err = ERROR_SUCCESS;
4227
- wchar_t * wpath = create_unc_path (pathbuf, err);
4228
- if (err != ERROR_SUCCESS) {
4229
- if (wpath != NULL ) {
4230
- destroy_unc_path (wpath);
4231
- }
4232
- os::free (pathbuf);
4233
- errno = err;
4234
- return -1 ;
4235
- }
4236
- BOOL bret = ::GetFileAttributesExW (wpath, GetFileExInfoStandard, &file_data);
4237
- if (!bret) {
4238
- errno = ::GetLastError ();
4239
- ret = -1 ;
4240
- } else {
4241
- file_attribute_data_to_stat (sbuf, file_data);
4242
- ret = 0 ;
4243
- }
4244
- destroy_unc_path (wpath);
4266
+
4267
+ WIN32_FILE_ATTRIBUTE_DATA file_data;;
4268
+ BOOL bret = ::GetFileAttributesExW (wide_path, GetFileExInfoStandard, &file_data);
4269
+ os::free (wide_path);
4270
+
4271
+ if (!bret) {
4272
+ errno = ::GetLastError ();
4273
+ return -1 ;
4245
4274
}
4246
- os::free (pathbuf);
4247
- return ret;
4275
+
4276
+ file_attribute_data_to_stat (sbuf, file_data);
4277
+ return 0 ;
4248
4278
}
4249
4279
4250
4280
static HANDLE create_read_only_file_handle (const char * file) {
4251
- if (file == NULL ) {
4252
- return INVALID_HANDLE_VALUE;
4253
- }
4281
+ errno_t err;
4282
+ wchar_t * wide_path = wide_abs_unc_path (file, err);
4254
4283
4255
- char * nativepath = (char *)os::strdup (file, mtInternal);
4256
- if (nativepath == NULL ) {
4257
- errno = ENOMEM;
4284
+ if (wide_path == NULL ) {
4285
+ errno = err;
4258
4286
return INVALID_HANDLE_VALUE;
4259
4287
}
4260
- os::native_path (nativepath);
4261
4288
4262
- size_t len = strlen (nativepath);
4263
- HANDLE handle = INVALID_HANDLE_VALUE;
4289
+ HANDLE handle = ::CreateFileW (wide_path, 0 , FILE_SHARE_READ,
4290
+ NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
4291
+ os::free (wide_path);
4264
4292
4265
- if (len < MAX_PATH) {
4266
- handle = ::CreateFile (nativepath, 0 , FILE_SHARE_READ,
4267
- NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
4268
- } else {
4269
- errno_t err = ERROR_SUCCESS;
4270
- wchar_t * wfile = create_unc_path (nativepath, err);
4271
- if (err != ERROR_SUCCESS) {
4272
- if (wfile != NULL ) {
4273
- destroy_unc_path (wfile);
4274
- }
4275
- os::free (nativepath);
4276
- return INVALID_HANDLE_VALUE;
4277
- }
4278
- handle = ::CreateFileW (wfile, 0 , FILE_SHARE_READ,
4279
- NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
4280
- destroy_unc_path (wfile);
4281
- }
4282
-
4283
- os::free (nativepath);
4284
4293
return handle;
4285
4294
}
4286
4295
@@ -4329,7 +4338,6 @@ bool os::same_files(const char* file1, const char* file2) {
4329
4338
return result;
4330
4339
}
4331
4340
4332
-
4333
4341
#define FT2INT64 (ft ) \
4334
4342
((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime ))
4335
4343
@@ -4434,38 +4442,22 @@ bool os::dont_yield() {
4434
4442
return DontYieldALot;
4435
4443
}
4436
4444
4437
- // This method is a slightly reworked copy of JDK's sysOpen
4438
- // from src/windows/hpi/src/sys_api_md.c
4439
-
4440
4445
int os::open (const char *path, int oflag, int mode) {
4441
- char * pathbuf = (char *)os::strdup (path, mtInternal);
4442
- if (pathbuf == NULL ) {
4443
- errno = ENOMEM;
4446
+ errno_t err;
4447
+ wchar_t * wide_path = wide_abs_unc_path (path, err);
4448
+
4449
+ if (wide_path == NULL ) {
4450
+ errno = err;
4444
4451
return -1 ;
4445
4452
}
4446
- os::native_path (pathbuf);
4447
- int ret;
4448
- if (strlen (path) < MAX_PATH) {
4449
- ret = ::open (pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
4450
- } else {
4451
- errno_t err = ERROR_SUCCESS;
4452
- wchar_t * wpath = create_unc_path (pathbuf, err);
4453
- if (err != ERROR_SUCCESS) {
4454
- if (wpath != NULL ) {
4455
- destroy_unc_path (wpath);
4456
- }
4457
- os::free (pathbuf);
4458
- errno = err;
4459
- return -1 ;
4460
- }
4461
- ret = ::_wopen (wpath, oflag | O_BINARY | O_NOINHERIT, mode);
4462
- if (ret == -1 ) {
4463
- errno = ::GetLastError ();
4464
- }
4465
- destroy_unc_path (wpath);
4453
+ int fd = ::_wopen (wide_path, oflag | O_BINARY | O_NOINHERIT, mode);
4454
+ os::free (wide_path);
4455
+
4456
+ if (fd == -1 ) {
4457
+ errno = ::GetLastError ();
4466
4458
}
4467
- os::free (pathbuf);
4468
- return ret ;
4459
+
4460
+ return fd ;
4469
4461
}
4470
4462
4471
4463
FILE* os::open (int fd, const char * mode) {
@@ -4474,37 +4466,26 @@ FILE* os::open(int fd, const char* mode) {
4474
4466
4475
4467
// Is a (classpath) directory empty?
4476
4468
bool os::dir_is_empty (const char * path) {
4477
- char * search_path = (char *)os::malloc (strlen (path) + 3 , mtInternal);
4478
- if (search_path == NULL ) {
4479
- errno = ENOMEM;
4480
- return false ;
4481
- }
4482
- strcpy (search_path, path);
4483
- os::native_path (search_path);
4484
- // Append "*", or possibly "\\*", to path
4485
- if (search_path[1 ] == ' :' &&
4486
- (search_path[2 ] == ' \0 ' ||
4487
- (search_path[2 ] == ' \\ ' && search_path[3 ] == ' \0 ' ))) {
4488
- // No '\\' needed for cases like "Z:" or "Z:\"
4489
- strcat (search_path, " *" );
4490
- }
4491
- else {
4492
- strcat (search_path, " \\ *" );
4493
- }
4494
- errno_t err = ERROR_SUCCESS;
4495
- wchar_t * wpath = create_unc_path (search_path, err);
4496
- if (err != ERROR_SUCCESS) {
4497
- if (wpath != NULL ) {
4498
- destroy_unc_path (wpath);
4499
- }
4500
- os::free (search_path);
4469
+ errno_t err;
4470
+ wchar_t * wide_path = wide_abs_unc_path (path, err, 2 );
4471
+
4472
+ if (wide_path == NULL ) {
4501
4473
errno = err;
4502
4474
return false ;
4503
4475
}
4476
+
4477
+ // Make sure we end with "\\*"
4478
+ if (wide_path[wcslen (wide_path) - 1 ] == L' \\ ' ) {
4479
+ wcscat (wide_path, L" *" );
4480
+ } else {
4481
+ wcscat (wide_path, L" \\ *" );
4482
+ }
4483
+
4504
4484
WIN32_FIND_DATAW fd;
4505
- HANDLE f = ::FindFirstFileW (wpath , &fd);
4506
- destroy_unc_path (wpath );
4485
+ HANDLE f = ::FindFirstFileW (wide_path , &fd);
4486
+ os::free (wide_path );
4507
4487
bool is_empty = true ;
4488
+
4508
4489
if (f != INVALID_HANDLE_VALUE) {
4509
4490
while (is_empty && ::FindNextFileW (f, &fd)) {
4510
4491
// An empty directory contains only the current directory file
@@ -4515,8 +4496,10 @@ bool os::dir_is_empty(const char* path) {
4515
4496
}
4516
4497
}
4517
4498
FindClose (f);
4499
+ } else {
4500
+ errno = ::GetLastError ();
4518
4501
}
4519
- os::free (search_path);
4502
+
4520
4503
return is_empty;
4521
4504
}
4522
4505
0 commit comments