From: Michihiro NAKAJIMA Date: Thu, 29 Dec 2011 02:19:45 +0000 (-0500) Subject: Improve directory traversals on Windows to correctly handle the path which starts... X-Git-Tag: v3.0.4~2^2~248 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90bd7efcd69151f95c7662e121efe907284f7f25;p=thirdparty%2Flibarchive.git Improve directory traversals on Windows to correctly handle the path which starts with "\\?\" or "//?/". SVN-Revision: 4024 --- diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index d8a1f5577..e5188c994 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -1277,8 +1277,9 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) /* First item is set up a lot like a symlink traversal. */ /* printf("Looking for wildcard in %s\n", path); */ - /* TODO: wildcard detection here screws up on \\?\c:\ UNC names */ - if (wcschr(base, L'*') || wcschr(base, L'?')) { + if (!(base[0] == L'/' && base[1] == L'/' && + base[2] == L'?' && base[3] == L'/') && + (wcschr(base, L'*') || wcschr(base, L'?'))) { // It has a wildcard in it... // Separate the last element. p = wcsrchr(base, L'/'); @@ -1374,7 +1375,9 @@ tree_next(struct tree *t) if (t->stack->flags & needsFirstVisit) { wchar_t *d = t->stack->name.s; t->stack->flags &= ~needsFirstVisit; - if (wcschr(d, L'*') || wcschr(d, L'?')) { + if (!(d[0] == L'/' && d[1] == L'/' && + d[2] == L'?' && d[3] == L'/') && + (wcschr(d, L'*') || wcschr(d, L'?'))) { r = tree_dir_next_windows(t, d); if (r == 0) continue; diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c index a1d6e1ad5..c3288730c 100644 --- a/libarchive/test/test_read_disk_directory_traversals.c +++ b/libarchive/test/test_read_disk_directory_traversals.c @@ -42,6 +42,9 @@ test_basic(void) size_t size; int64_t offset; int file_count; +#if defined(_WIN32) && !defined(__CYGWIN__) + wchar_t *wcwd, *fullpath; +#endif assertMakeDir("dir1", 0755); assertMakeFile("dir1/file1", 0644, "0123456789"); @@ -351,6 +354,38 @@ test_basic(void) /* Close the disk object. */ assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + + /* + * Test for a full-path beginning with "//?/" + */ + wcwd = _wgetcwd(NULL, 0); + fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32)); + wcscpy(fullpath, L"//?/"); + wcscat(fullpath, wcwd); + wcscat(fullpath, L"/dir1/file1"); + free(wcwd); + assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath)); + while ((wcwd = wcschr(fullpath, L'\\')) != NULL) + *wcwd = L'/'; + + /* dir1/file1 */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae)); + assertEqualWString(archive_entry_pathname_w(ae), fullpath); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualInt(archive_entry_size(ae), 10); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 10); + assertEqualInt((int)offset, 0); + assertEqualMem(p, "0123456789", 10); + + /* There is no entry. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); + + /* Close the disk object. */ + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + free(fullpath); + #endif /*