summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2015-08-31 17:52:47 +0300
committerEli Zaretskii <eliz@gnu.org>2015-08-31 17:52:47 +0300
commit5ee3ef8e1867d284be0ff9f654f8bde46e751978 (patch)
tree6e82d1b10ae6b1f8f208ed43e2cc55ff7eb160b8
parent697be62c5f2b86e8ad93dfcaa0df07890c24d989 (diff)
downloademacs-5ee3ef8e1867d284be0ff9f654f8bde46e751978.tar.gz
Fix handling long file names in readdir on MS-Windows
* src/w32.c (sys_readdir): Append "\*" to the directory after converting it to UTF-16/ANSI, not before, to avoid overflowing the 260-character limit on file names in filename_to_utf16/ansi.
-rw-r--r--src/w32.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/w32.c b/src/w32.c
index 60fbe92e082..dea8431ed7a 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3399,30 +3399,41 @@ sys_readdir (DIR *dirp)
/* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
else if (dir_find_handle == INVALID_HANDLE_VALUE)
{
- char filename[MAX_UTF8_PATH + 2];
+ char filename[MAX_UTF8_PATH];
int ln;
+ bool last_slash = true;
+ /* Note: We don't need to worry about dir_pathname being longer
+ than MAX_UTF8_PATH, as sys_opendir already took care of that
+ when it called map_w32_filename: that function will put a "?"
+ in its return value in that case, thus failing all the calls
+ below. */
strcpy (filename, dir_pathname);
ln = strlen (filename);
if (!IS_DIRECTORY_SEP (filename[ln - 1]))
- filename[ln++] = '\\';
- strcpy (filename + ln, "*");
+ last_slash = false;
/* Note: No need to resolve symlinks in FILENAME, because
FindFirst opens the directory that is the target of a
symlink. */
if (w32_unicode_filenames)
{
- wchar_t fnw[MAX_PATH];
+ wchar_t fnw[MAX_PATH + 2];
filename_to_utf16 (filename, fnw);
+ if (!last_slash)
+ wcscat (fnw, L"\\");
+ wcscat (fnw, L"*");
dir_find_handle = FindFirstFileW (fnw, &dir_find_data_w);
}
else
{
- char fna[MAX_PATH];
+ char fna[MAX_PATH + 2];
filename_to_ansi (filename, fna);
+ if (!last_slash)
+ strcat (fna, "\\");
+ strcat (fna, "*");
/* If FILENAME is not representable by the current ANSI
codepage, we don't want FindFirstFileA to interpret the
'?' characters as a wildcard. */
@@ -3860,6 +3871,8 @@ w32_accessible_directory_p (const char *dirname, ptrdiff_t dirlen)
bool last_slash = dirlen > 0 && IS_DIRECTORY_SEP (dirname[dirlen - 1]);
HANDLE dh;
+ /* Note: map_w32_filename makes sure DIRNAME is not longer than
+ MAX_UTF8_PATH. */
strcpy (pattern, map_w32_filename (dirname, NULL));
/* Note: No need to resolve symlinks in FILENAME, because FindFirst