From 44ae1364908f91d877a6afa9bdd394e31fbd8311 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 30 Jan 2015 08:48:32 +0200 Subject: [PATCH] Fix error messages when readdir cannot open a directory on MS-Windows src/dired.c (read_dirent): Accept an additional argument FIRST_ENTRY. If readdir fails with ENOENT or EACCES the first time it is called, report the error as if it happened in open_directory. (directory_files_internal, file_name_completion): Adjust callers or read_dirent. --- src/ChangeLog | 9 +++++++++ src/dired.c | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 67b6fa01b5..fc4258c9bf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2015-01-30 Eli Zaretskii + + * dired.c (read_dirent): Accept an additional argument + FIRST_ENTRY. If readdir fails with ENOENT or EACCES the first + time it is called, report the error as if it happened in + open_directory. + (directory_files_internal, file_name_completion): Adjust callers + or read_dirent. + 2015-01-30 Paul Eggert Refactor calls to opendir for simplicity diff --git a/src/dired.c b/src/dired.c index 7982c1fb8e..56d6de2d35 100644 --- a/src/dired.c +++ b/src/dired.c @@ -124,10 +124,11 @@ directory_files_internal_unwind (void *dh) /* Return the next directory entry from DIR; DIR's name is DIRNAME. If there are no more directory entries, return a null pointer. - Signal any unrecoverable errors. */ + Signal any unrecoverable errors. FIRST_ENTRY true means this is + the first call after open_directory. */ static struct dirent * -read_dirent (DIR *dir, Lisp_Object dirname) +read_dirent (DIR *dir, Lisp_Object dirname, bool first_entry) { while (true) { @@ -136,7 +137,16 @@ read_dirent (DIR *dir, Lisp_Object dirname) if (dp || errno == 0) return dp; if (! (errno == EAGAIN || errno == EINTR)) - report_file_error ("Reading directory", dirname); + { + /* The MS-Windows implementation of 'opendir' doesn't + actually open a directory until the first call to + 'readdir'. If 'readdir' fails to open the directory, it + sets errno to ENOENT or EACCES, see w32.c. */ + if (first_entry && (errno == ENOENT || errno == EACCES)) + report_file_error ("Opening directory", dirname); + else + report_file_error ("Reading directory", dirname); + } QUIT; } } @@ -239,7 +249,8 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, needsep = 1; /* Loop reading directory entries. */ - for (struct dirent *dp; (dp = read_dirent (d, directory)); ) + bool first_entry = true; + for (struct dirent *dp; (dp = read_dirent (d, directory, first_entry)); ) { ptrdiff_t len = dirent_namelen (dp); Lisp_Object name = make_unibyte_string (dp->d_name, len); @@ -247,6 +258,8 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, struct gcpro gcpro1, gcpro2; GCPRO2 (finalname, name); + first_entry = false; + /* Note: DECODE_FILE can GC; it should protect its argument, though. */ name = DECODE_FILE (name); @@ -486,11 +499,13 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, record_unwind_protect_ptr (directory_files_internal_unwind, d); /* Loop reading directory entries. */ - for (struct dirent *dp; (dp = read_dirent (d, dirname)); ) + bool first_entry = true; + for (struct dirent *dp; (dp = read_dirent (d, dirname, first_entry)); ) { ptrdiff_t len = dirent_namelen (dp); bool canexclude = 0; + first_entry = false; QUIT; if (len < SCHARS (encoded_file) || (scmp (dp->d_name, SSDATA (encoded_file), -- 2.39.2