83 |
83 |
84 EXPECT_EQ(expected_location, actual_location) |
84 EXPECT_EQ(expected_location, actual_location) |
85 << "Failed to allocate memory at requested location " << expected_location << " of size " << expected_allocation_size; |
85 << "Failed to allocate memory at requested location " << expected_location << " of size " << expected_allocation_size; |
86 } |
86 } |
87 |
87 |
|
88 // The types of path modifications we randomly apply to a path. They should not change the file designated by the path. |
|
89 enum ModsFilter { |
|
90 Allow_None = 0, // No modifications |
|
91 Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1. |
|
92 Allow_Dot_Path = 2, // Add /. segments at random positions |
|
93 Allow_Dot_Dot_Path = 4, // Add /../<correct-dir> segments at random positions. |
|
94 Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path |
|
95 }; |
|
96 |
|
97 // The mode in which to run. |
|
98 enum Mode { |
|
99 TEST, // Runs the test. This is the normal modus. |
|
100 EXAMPLES, // Runs example which document the behaviour of the Windows system calls. |
|
101 BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath. |
|
102 }; |
|
103 |
|
104 // Parameters of the test. |
|
105 static ModsFilter mods_filter = Allow_All; |
|
106 static int mods_per_path = 50; // The number of variants of a path we try. |
|
107 static Mode mode = TEST; |
|
108 |
|
109 |
|
110 // Utility methods |
|
111 static void get_current_dir_w(wchar_t* path, size_t size) { |
|
112 DWORD count = GetCurrentDirectoryW((DWORD) size, path); |
|
113 EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError(); |
|
114 EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size; |
|
115 } |
|
116 |
|
117 #define WITH_ABS_PATH(path) \ |
|
118 wchar_t abs_path[JVM_MAXPATHLEN]; \ |
|
119 wchar_t cwd[JVM_MAXPATHLEN]; \ |
|
120 get_current_dir_w(cwd, JVM_MAXPATHLEN); \ |
|
121 wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path)) |
|
122 |
|
123 static bool file_exists_w(const wchar_t* path) { |
|
124 WIN32_FILE_ATTRIBUTE_DATA file_data; |
|
125 return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); |
|
126 } |
|
127 |
|
128 static void create_rel_directory_w(const wchar_t* path) { |
|
129 WITH_ABS_PATH(path); |
|
130 EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create directory: \"" << path << "\" already exists"; |
|
131 BOOL result = CreateDirectoryW(abs_path, NULL); |
|
132 EXPECT_TRUE(result) << "Failed to create directory \"" << path << "\" " << GetLastError(); |
|
133 } |
|
134 |
|
135 static void delete_empty_rel_directory_w(const wchar_t* path) { |
|
136 WITH_ABS_PATH(path); |
|
137 EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists"; |
|
138 BOOL result = RemoveDirectoryW(abs_path); |
|
139 EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError(); |
|
140 } |
|
141 |
|
142 static void create_rel_file_w(const wchar_t* path) { |
|
143 WITH_ABS_PATH(path); |
|
144 EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create file: \"" << path << "\" already exists"; |
|
145 HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); |
|
146 EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError(); |
|
147 CloseHandle(h); |
|
148 } |
|
149 |
|
150 static void delete_rel_file_w(const wchar_t* path) { |
|
151 WITH_ABS_PATH(path); |
|
152 EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists"; |
|
153 BOOL result = DeleteFileW(abs_path); |
|
154 EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError(); |
|
155 } |
|
156 |
|
157 static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) { |
|
158 size_t converted; |
|
159 errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1); |
|
160 EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string"; |
|
161 |
|
162 return err == ERROR_SUCCESS; |
|
163 } |
|
164 |
|
165 static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) { |
|
166 size_t already_used = dest - start; |
|
167 size_t len = wcslen(to_copy); |
|
168 |
|
169 if (already_used + len < size) { |
|
170 wcscpy_s(dest, size - already_used, to_copy); |
|
171 } |
|
172 |
|
173 return dest + wcslen(to_copy); |
|
174 } |
|
175 |
|
176 // The currently finite list of seperator sequences we might use instead of '\\'. |
|
177 static const wchar_t* sep_replacements[] = { |
|
178 L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/" |
|
179 }; |
|
180 |
|
181 // Takes a path and modifies it in a way that it should still designate the same file. |
|
182 static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) { |
|
183 wchar_t* dest = result; |
|
184 const wchar_t* src = path; |
|
185 const wchar_t* path_start; |
|
186 |
|
187 if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) { |
|
188 path_start = src + 8; |
|
189 } else if (wcsncmp(src, L"\\\\?\\", 4) == 0) { |
|
190 if (src[5] == L':') { |
|
191 path_start = src + 6; |
|
192 } else { |
|
193 path_start = wcschr(src + 4, L'\\'); |
|
194 } |
|
195 } else if (wcsncmp(src, L"\\\\", 2) == 0) { |
|
196 path_start = wcschr(src + 2, L'?'); |
|
197 |
|
198 if (path_start == NULL) { |
|
199 path_start = wcschr(src + 2, L'\\'); |
|
200 } else { |
|
201 path_start = wcschr(path_start, L'\\'); |
|
202 } |
|
203 } else { |
|
204 path_start = wcschr(src + 1, L'\\'); |
|
205 } |
|
206 |
|
207 bool allow_sep_change = (mods_filter & Allow_Sep_Mods) && (os::random() & 1) == 0; |
|
208 bool allow_dot_change = (mods_filter & Allow_Dot_Path) && (os::random() & 1) == 0; |
|
209 bool allow_dotdot_change = (mods_filter & Allow_Dot_Dot_Path) && (os::random() & 1) == 0; |
|
210 |
|
211 while ((*src != L'\0') && (result + size > dest)) { |
|
212 wchar_t c = *src; |
|
213 *dest = c; |
|
214 ++src; |
|
215 ++dest; |
|
216 |
|
217 if (c == L'\\') { |
|
218 if (allow_sep_change && (os::random() & 3) == 3) { |
|
219 int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0])); |
|
220 |
|
221 if (i >= 0) { |
|
222 const wchar_t* replacement = sep_replacements[i]; |
|
223 dest = my_wcscpy_s(dest - 1, size, result, replacement); |
|
224 } |
|
225 } else if (path_start != NULL) { |
|
226 if (allow_dotdot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { |
|
227 wchar_t const* last_sep = src - 2; |
|
228 |
|
229 while (last_sep[0] != L'\\') { |
|
230 --last_sep; |
|
231 } |
|
232 |
|
233 if (last_sep > path_start) { |
|
234 dest = my_wcscpy_s(dest, size, result, L"../"); |
|
235 src = last_sep + 1; |
|
236 } |
|
237 } else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { |
|
238 dest = my_wcscpy_s(dest, size, result, L"./"); |
|
239 } |
|
240 } |
|
241 } |
|
242 } |
|
243 |
|
244 while (is_dir && ((os::random() & 15) == 1)) { |
|
245 dest = my_wcscpy_s(dest, size, result, L"/"); |
|
246 } |
|
247 |
|
248 if (result + size > dest) { |
|
249 *dest = L'\0'; |
|
250 } |
|
251 |
|
252 // Use this modification only if not too close to the max size. |
|
253 return result + size - 10 > dest; |
|
254 } |
|
255 |
|
256 static void check_dir_impl(wchar_t* path, bool should_be_empty) { |
|
257 char buf[JVM_MAXPATHLEN]; |
|
258 |
|
259 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
260 struct stat st; |
|
261 EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; |
|
262 EXPECT_EQ(st.st_mode & S_IFMT, S_IFDIR) << "\"" << path << "\" is not a directory according to os::stat"; |
|
263 errno = ERROR_SUCCESS; |
|
264 bool is_empty = os::dir_is_empty(buf); |
|
265 errno_t err = errno; |
|
266 EXPECT_EQ(is_empty, should_be_empty) << "os::dir_is_empty assumed \"" << path << "\" is " |
|
267 << (should_be_empty ? "not ": "") << "empty"; |
|
268 EXPECT_EQ(err, ERROR_SUCCESS) << "os::dir_is_empty failed for \"" << path << "\"with errno " << err; |
|
269 } |
|
270 } |
|
271 |
|
272 static void check_file_impl(wchar_t* path) { |
|
273 char buf[JVM_MAXPATHLEN]; |
|
274 |
|
275 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
276 struct stat st; |
|
277 EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; |
|
278 EXPECT_EQ(st.st_mode & S_IFMT, S_IFREG) << "\"" << path << "\" is not a regular file according to os::stat"; |
|
279 int fd = os::open(buf, O_RDONLY, 0); |
|
280 EXPECT_NE(fd, -1) << "os::open failed for \"" << path << "\" with errno " << errno; |
|
281 if (fd >= 0) { |
|
282 ::close(fd); |
|
283 } |
|
284 } |
|
285 } |
|
286 |
|
287 static void check_file_not_present_impl(wchar_t* path) { |
|
288 char buf[JVM_MAXPATHLEN]; |
|
289 |
|
290 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
291 struct stat st; |
|
292 int stat_ret; |
|
293 EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\""; |
|
294 if (stat_ret != -1) { |
|
295 // Only check open if stat not already failed. |
|
296 int fd = os::open(buf, O_RDONLY, 0); |
|
297 EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\""; |
|
298 if (fd >= 0) { |
|
299 ::close(fd); |
|
300 } |
|
301 } |
|
302 } |
|
303 } |
|
304 |
|
305 static void check_dir(wchar_t* path, bool should_be_empty) { |
|
306 check_dir_impl(path, should_be_empty); |
|
307 |
|
308 for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { |
|
309 wchar_t tmp[JVM_MAXPATHLEN]; |
|
310 if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) { |
|
311 check_dir_impl(tmp, should_be_empty); |
|
312 } |
|
313 } |
|
314 } |
|
315 |
|
316 static void check_file(wchar_t* path) { |
|
317 check_file_impl(path); |
|
318 |
|
319 // Check os::same_files at least somewhat. |
|
320 char buf[JVM_MAXPATHLEN]; |
|
321 |
|
322 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
323 wchar_t mod[JVM_MAXPATHLEN]; |
|
324 |
|
325 if (unnormalize_path(mod, JVM_MAXPATHLEN, false, path)) { |
|
326 char mod_c[JVM_MAXPATHLEN]; |
|
327 if (convert_to_cstring(mod_c, JVM_MAXPATHLEN, mod)) { |
|
328 EXPECT_EQ(os::same_files(buf, mod_c), true) << "os::same files failed for \\" << path << "\" and \"" << mod_c << "\""; |
|
329 } |
|
330 } |
|
331 } |
|
332 |
|
333 for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { |
|
334 wchar_t tmp[JVM_MAXPATHLEN]; |
|
335 if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { |
|
336 check_file_impl(tmp); |
|
337 } |
|
338 } |
|
339 } |
|
340 |
|
341 static void check_file_not_present(wchar_t* path) { |
|
342 check_file_not_present_impl(path); |
|
343 |
|
344 for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { |
|
345 wchar_t tmp[JVM_MAXPATHLEN]; |
|
346 if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { |
|
347 check_file_not_present_impl(tmp); |
|
348 } |
|
349 } |
|
350 } |
|
351 |
|
352 static void record_path(char const* name, char const* len_name, wchar_t* path) { |
|
353 char buf[JVM_MAXPATHLEN]; |
|
354 |
|
355 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
356 ::testing::Test::RecordProperty(name, buf); |
|
357 snprintf(buf, JVM_MAXPATHLEN, "%d", (int) wcslen(path)); |
|
358 ::testing::Test::RecordProperty(len_name, buf); |
|
359 } |
|
360 } |
|
361 |
|
362 static void bench_path(wchar_t* path) { |
|
363 char buf[JVM_MAXPATHLEN]; |
|
364 int reps = 100000; |
|
365 |
|
366 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
367 jlong wtime[2]; |
|
368 |
|
369 for (int t = 0; t < 2; ++t) { |
|
370 wtime[t] = os::javaTimeNanos(); |
|
371 |
|
372 for (int i = 0; i < reps; ++i) { |
|
373 bool succ = false; |
|
374 size_t buf_len = strlen(buf); |
|
375 wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal); |
|
376 |
|
377 if (w_path != NULL) { |
|
378 size_t converted_chars; |
|
379 if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) { |
|
380 if (t == 1) { |
|
381 wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal); |
|
382 |
|
383 if (tmp) { |
|
384 if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) { |
|
385 succ = true; |
|
386 } |
|
387 |
|
388 // Note that we really don't use the full path name, but just add the cost of running _wfullpath. |
|
389 os::free(tmp); |
|
390 } |
|
391 if (!succ) { |
|
392 printf("Failed fullpathing \"%s\"\n", buf); |
|
393 return; |
|
394 } |
|
395 succ = false; |
|
396 } |
|
397 HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
|
398 |
|
399 if (h != INVALID_HANDLE_VALUE) { |
|
400 ::CloseHandle(h); |
|
401 succ = true; |
|
402 } |
|
403 } |
|
404 } |
|
405 |
|
406 os::free(w_path); |
|
407 if (!succ) { |
|
408 printf("Failed getting W*attr. \"%s\"\n", buf); |
|
409 return; |
|
410 } |
|
411 } |
|
412 |
|
413 wtime[t] = os::javaTimeNanos() - wtime[t]; |
|
414 } |
|
415 |
|
416 jlong ctime = os::javaTimeNanos(); |
|
417 |
|
418 for (int i = 0; i < reps; ++i) { |
|
419 HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
|
420 |
|
421 if (h == INVALID_HANDLE_VALUE) { |
|
422 return; |
|
423 } |
|
424 |
|
425 ::CloseHandle(h); |
|
426 } |
|
427 |
|
428 ctime = os::javaTimeNanos() - ctime; |
|
429 |
|
430 printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf, |
|
431 0.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps); |
|
432 } |
|
433 } |
|
434 |
|
435 static void print_attr_result_for_path(wchar_t* path) { |
|
436 WIN32_FILE_ATTRIBUTE_DATA file_data; |
|
437 struct stat st; |
|
438 char buf[JVM_MAXPATHLEN]; |
|
439 wchar_t abs[JVM_MAXPATHLEN]; |
|
440 |
|
441 _wfullpath(abs, path, JVM_MAXPATHLEN); |
|
442 printf("Checking \"%ls\" (%d chars):\n", path, (int) wcslen(path)); |
|
443 printf("_wfullpath %ls (%d chars)\n", abs, (int) wcslen(abs)); |
|
444 BOOL bret = ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); |
|
445 printf("GetFileAttributesExW() %s\n", bret ? "success" : "failed"); |
|
446 |
|
447 if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { |
|
448 bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data); |
|
449 printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed"); |
|
450 |
|
451 bool succ = os::stat(buf, &st) != -1; |
|
452 printf("os::stat() %s\n", succ ? "success" : "failed"); |
|
453 } |
|
454 } |
|
455 |
|
456 static void print_attr_result(wchar_t* format, ...) { |
|
457 va_list argptr; |
|
458 wchar_t buf[JVM_MAXPATHLEN]; |
|
459 |
|
460 va_start(argptr, format); |
|
461 wvsprintfW(buf, format, argptr); |
|
462 print_attr_result_for_path(buf); |
|
463 va_end(argptr); |
|
464 } |
|
465 |
|
466 #define RECORD_PATH(name) record_path(#name, #name "Len", name) |
|
467 #define NAME_PART_50 L"01234567890123456789012345678901234567890123456789" |
|
468 #define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 |
|
469 |
|
470 // Test which tries to find out if the os::stat, os::open, os::same_files and os::dir_is_empty methods |
|
471 // can handle long path names correctly. |
|
472 TEST_VM(os_windows, handle_long_paths) { |
|
473 static wchar_t cwd[JVM_MAXPATHLEN]; |
|
474 static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN]; |
|
475 static wchar_t long_rel_path[JVM_MAXPATHLEN]; |
|
476 static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN]; |
|
477 static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN]; |
|
478 static wchar_t file_rel_path[JVM_MAXPATHLEN]; |
|
479 static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN]; |
|
480 static wchar_t nearly_long_path[JVM_MAXPATHLEN]; |
|
481 static wchar_t empty_dir_path[JVM_MAXPATHLEN]; |
|
482 static wchar_t not_empty_dir_path[JVM_MAXPATHLEN]; |
|
483 static wchar_t nearly_long_file_path[JVM_MAXPATHLEN]; |
|
484 static wchar_t file_path[JVM_MAXPATHLEN]; |
|
485 static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN]; |
|
486 static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN]; |
|
487 static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN]; |
|
488 static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN]; |
|
489 static wchar_t file_unc_path[JVM_MAXPATHLEN]; |
|
490 static wchar_t root_dir_path[JVM_MAXPATHLEN]; |
|
491 static wchar_t root_rel_dir_path[JVM_MAXPATHLEN]; |
|
492 |
|
493 wchar_t* dir_prefix = L"os_windows_long_paths_dir_"; |
|
494 wchar_t* empty_dir_name = L"empty_directory_with_long_path"; |
|
495 wchar_t* not_empty_dir_name = L"not_empty_directory_with_long_path"; |
|
496 wchar_t* file_name = L"file"; |
|
497 wchar_t dir_letter; |
|
498 WIN32_FILE_ATTRIBUTE_DATA file_data; |
|
499 bool can_test_unc = false; |
|
500 |
|
501 get_current_dir_w(cwd, sizeof(cwd) / sizeof(wchar_t)); |
|
502 dir_letter = (cwd[1] == L':' ? cwd[0] : L'\0'); |
|
503 int cwd_len = (int) wcslen(cwd); |
|
504 int dir_prefix_len = (int) wcslen(dir_prefix); |
|
505 int rel_path_len = MAX2(dir_prefix_len, 235 - cwd_len); |
|
506 |
|
507 memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len); |
|
508 |
|
509 for (int i = dir_prefix_len; i < rel_path_len; ++i) { |
|
510 nearly_long_rel_path[i] = L'L'; |
|
511 } |
|
512 |
|
513 nearly_long_rel_path[rel_path_len] = L'\0'; |
|
514 |
|
515 wsprintfW(long_rel_path, L"%ls\\%ls", nearly_long_rel_path, NAME_PART_250); |
|
516 wsprintfW(empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, empty_dir_name); |
|
517 wsprintfW(not_empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, not_empty_dir_name); |
|
518 wsprintfW(nearly_long_file_rel_path, L"%ls\\%ls", nearly_long_rel_path, file_name); |
|
519 wsprintfW(file_rel_path, L"%ls\\%ls\\%ls", nearly_long_rel_path, not_empty_dir_name, file_name); |
|
520 wsprintfW(nearly_long_path, L"\\\\?\\%ls\\%ls", cwd, nearly_long_rel_path); |
|
521 wsprintfW(empty_dir_path, L"%ls\\%ls", nearly_long_path, empty_dir_name); |
|
522 wsprintfW(not_empty_dir_path, L"%ls\\%ls", nearly_long_path, not_empty_dir_name); |
|
523 wsprintfW(nearly_long_file_path, L"%ls\\%ls", nearly_long_path, file_name); |
|
524 wsprintfW(file_path, L"%ls\\%ls\\%ls", nearly_long_path, not_empty_dir_name, file_name); |
|
525 wsprintfW(nearly_long_unc_path, L"\\\\localhost\\%lc$\\%s", dir_letter, nearly_long_path + 7); |
|
526 wsprintfW(empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, empty_dir_name); |
|
527 wsprintfW(not_empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, not_empty_dir_name); |
|
528 wsprintfW(nearly_long_file_unc_path, L"%ls\\%ls", nearly_long_unc_path, file_name); |
|
529 wsprintfW(file_unc_path, L"%s\\%s\\%s", nearly_long_unc_path, not_empty_dir_name, file_name); |
|
530 wsprintfW(root_dir_path, L"%lc:\\", dir_letter); |
|
531 wsprintfW(root_rel_dir_path, L"%lc:", dir_letter); |
|
532 |
|
533 RECORD_PATH(long_rel_path); |
|
534 RECORD_PATH(nearly_long_rel_path); |
|
535 RECORD_PATH(nearly_long_path); |
|
536 RECORD_PATH(nearly_long_unc_path); |
|
537 RECORD_PATH(empty_dir_rel_path); |
|
538 RECORD_PATH(empty_dir_path); |
|
539 RECORD_PATH(empty_dir_unc_path); |
|
540 RECORD_PATH(not_empty_dir_rel_path); |
|
541 RECORD_PATH(not_empty_dir_path); |
|
542 RECORD_PATH(not_empty_dir_unc_path); |
|
543 RECORD_PATH(nearly_long_file_rel_path); |
|
544 RECORD_PATH(nearly_long_file_path); |
|
545 RECORD_PATH(nearly_long_file_unc_path); |
|
546 RECORD_PATH(file_rel_path); |
|
547 RECORD_PATH(file_path); |
|
548 RECORD_PATH(file_unc_path); |
|
549 |
|
550 create_rel_directory_w(nearly_long_rel_path); |
|
551 create_rel_directory_w(long_rel_path); |
|
552 create_rel_directory_w(empty_dir_rel_path); |
|
553 create_rel_directory_w(not_empty_dir_rel_path); |
|
554 create_rel_file_w(nearly_long_file_rel_path); |
|
555 create_rel_file_w(file_rel_path); |
|
556 |
|
557 // For UNC path test we assume that the current DRIVE has a share |
|
558 // called "<DRIVELETTER>$" (so for D: we expect \\localhost\D$ to be |
|
559 // the same). Since this is only an assumption, we have to skip |
|
560 // the UNC tests if the share is missing. |
|
561 if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) { |
|
562 printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter); |
|
563 } else { |
|
564 can_test_unc = true; |
|
565 } |
|
566 |
|
567 if (mode == BENCH) { |
|
568 bench_path(nearly_long_path + 4); |
|
569 bench_path(nearly_long_rel_path); |
|
570 bench_path(nearly_long_file_path + 4); |
|
571 bench_path(nearly_long_file_rel_path); |
|
572 } else if (mode == EXAMPLES) { |
|
573 printf("Working directory: %ls", cwd); |
|
574 |
|
575 if (dir_letter) { |
|
576 static wchar_t top_buf[JVM_MAXPATHLEN]; |
|
577 wchar_t* top_path = wcschr(cwd + 3, L'\\'); |
|
578 |
|
579 if (top_path) { |
|
580 size_t top_len = (top_path - cwd) - 3; |
|
581 |
|
582 memcpy(top_buf, cwd + 3, top_len * 2); |
|
583 top_buf[top_len] = L'\0'; |
|
584 top_path = top_buf; |
|
585 } |
|
586 |
|
587 print_attr_result(L"%lc:\\", dir_letter); |
|
588 print_attr_result(L"%lc:\\.\\", dir_letter); |
|
589 |
|
590 if (top_path) { |
|
591 print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path); |
|
592 } |
|
593 |
|
594 print_attr_result(L"%lc:", dir_letter); |
|
595 print_attr_result(L"%lc:.", dir_letter); |
|
596 print_attr_result(L"%lc:\\COM1", dir_letter); |
|
597 print_attr_result(L"%lc:\\PRN", dir_letter); |
|
598 print_attr_result(L"%lc:\\PRN\\COM1", dir_letter); |
|
599 print_attr_result(L"\\\\?\\UNC\\localhost\\%lc$\\", dir_letter); |
|
600 print_attr_result(L"\\\\?\\UNC\\\\localhost\\%lc$\\", dir_letter); |
|
601 print_attr_result(nearly_long_unc_path); |
|
602 print_attr_result(L"%ls\\.\\", nearly_long_unc_path); |
|
603 print_attr_result(L"%ls\\..\\%ls", nearly_long_unc_path, nearly_long_rel_path); |
|
604 print_attr_result(L"\\\\?\\UNC\\%ls", nearly_long_unc_path + 2); |
|
605 print_attr_result(file_unc_path); |
|
606 print_attr_result(L"%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path, not_empty_dir_name, not_empty_dir_name, file_name); |
|
607 print_attr_result(L"%ls\\%ls\\.\\%ls", nearly_long_unc_path, not_empty_dir_name, file_name); |
|
608 print_attr_result(L"\\\\?\\UNC\\%ls", file_unc_path + 2); |
|
609 print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\.\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, file_name); |
|
610 print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, not_empty_dir_name, file_name); |
|
611 } |
|
612 |
|
613 print_attr_result(nearly_long_rel_path); |
|
614 print_attr_result(L"%ls\\.\\", nearly_long_rel_path); |
|
615 print_attr_result(L"%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); |
|
616 print_attr_result(L"%\\\\?\\%ls", nearly_long_rel_path); |
|
617 print_attr_result(L"\\\\?\\%ls\\.\\", nearly_long_rel_path); |
|
618 print_attr_result(L"\\\\?\\%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); |
|
619 |
|
620 print_attr_result(nearly_long_path + 4); |
|
621 print_attr_result(L"%ls\\.\\", nearly_long_path + 4); |
|
622 print_attr_result(L"%ls\\..\\%ls", nearly_long_path + 4, nearly_long_rel_path); |
|
623 print_attr_result(nearly_long_path); |
|
624 print_attr_result(L"%ls\\.\\", nearly_long_path); |
|
625 print_attr_result(L"%ls\\..\\%ls", nearly_long_path, nearly_long_rel_path); |
|
626 } else { |
|
627 check_file_not_present(L""); |
|
628 |
|
629 // Check relative paths |
|
630 check_dir(nearly_long_rel_path, false); |
|
631 check_dir(long_rel_path, true); |
|
632 check_dir(empty_dir_rel_path, true); |
|
633 check_dir(not_empty_dir_rel_path, false); |
|
634 check_file(nearly_long_file_rel_path); |
|
635 check_file(file_rel_path); |
|
636 |
|
637 // Check absolute paths |
|
638 if (dir_letter) { |
|
639 check_dir(root_dir_path, false); |
|
640 check_dir(root_rel_dir_path, false); |
|
641 } |
|
642 |
|
643 check_dir(cwd, false); |
|
644 check_dir(nearly_long_path + 4, false); |
|
645 check_dir(empty_dir_path + 4, true); |
|
646 check_dir(not_empty_dir_path + 4, false); |
|
647 check_file(nearly_long_file_path + 4); |
|
648 check_file(file_path + 4); |
|
649 |
|
650 // Check UNC paths |
|
651 if (can_test_unc) { |
|
652 check_dir(nearly_long_unc_path, false); |
|
653 check_dir(empty_dir_unc_path, true); |
|
654 check_dir(not_empty_dir_unc_path, false); |
|
655 check_file(nearly_long_file_unc_path); |
|
656 check_file(file_unc_path); |
|
657 } |
|
658 |
|
659 // Check handling of <DRIVE>:/../<OTHER_DRIVE>:/path/... |
|
660 // The other drive letter should not overwrite the original one. |
|
661 if (dir_letter) { |
|
662 static wchar_t tmp[JVM_MAXPATHLEN]; |
|
663 wchar_t* other_letter = dir_letter == L'D' ? L"C" : L"D"; |
|
664 wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", nearly_long_file_path, other_letter, nearly_long_file_path + 2); |
|
665 check_file_not_present(tmp); |
|
666 wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", file_path, other_letter, file_path + 2); |
|
667 check_file_not_present(tmp); |
|
668 } |
|
669 } |
|
670 |
|
671 delete_rel_file_w(file_rel_path); |
|
672 delete_rel_file_w(nearly_long_file_rel_path); |
|
673 delete_empty_rel_directory_w(not_empty_dir_rel_path); |
|
674 delete_empty_rel_directory_w(empty_dir_rel_path); |
|
675 delete_empty_rel_directory_w(long_rel_path); |
|
676 delete_empty_rel_directory_w(nearly_long_rel_path); |
|
677 } |
|
678 |
88 #endif |
679 #endif |