[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: EMC Celerra: opendir bug? [Re: in ls.c, should check errno after rea
From: |
Jim Meyering |
Subject: |
Re: EMC Celerra: opendir bug? [Re: in ls.c, should check errno after readdir |
Date: |
Thu, 29 Aug 2002 12:52:26 +0200 |
User-agent: |
Gnus/5.090008 (Oort Gnus v0.08) Emacs/21.3.50 (i686-pc-linux-gnu) |
Ok. The Solaris5.8 man page for readdir suggests the same thing,
so I've changed remove.c and ls.c to check for readdir failures:
* src/remove.c (remove_cwd_entries): Use closedir (not CLOSEDIR)
when ignoring any return value.
* src/remove.c (remove_cwd_entries): Detect and diagnose readdir
failures. On some systems (at least EMC Celerra and Solaris5.8),
this appears to be necessary.
(is_empty_dir): Likewise. Also, always close directory handle.
* src/ls.c (print_dir): Likewise.
(print_dir): Rename local variable: reading -> dirp.
Reported by Mike Coleman.
There remain three files in lib/ that need similar changes.
Thanks again for the report and follow-up.
Index: ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.304
retrieving revision 1.306
diff -u -p -u -r1.304 -r1.306
--- ls.c 8 Jul 2002 09:12:48 -0000 1.304
+++ ls.c 29 Aug 2002 10:16:00 -0000 1.306
@@ -2030,14 +2030,14 @@ queue_directory (const char *name, const
static void
print_dir (const char *name, const char *realname)
{
- register DIR *reading;
+ register DIR *dirp;
register struct dirent *next;
register uintmax_t total_blocks = 0;
static int first = 1;
errno = 0;
- reading = opendir (name);
- if (!reading)
+ dirp = opendir (name);
+ if (!dirp)
{
error (0, errno, "%s", quotearg_colon (name));
exit_status = 1;
@@ -2047,7 +2047,7 @@ print_dir (const char *name, const char
if (LOOP_DETECT)
{
struct stat dir_stat;
- int fd = dirfd (reading);
+ int fd = dirfd (dirp);
/* If dirfd failed, endure the overhead of using stat. */
if ((0 <= fd
@@ -2077,23 +2077,43 @@ print_dir (const char *name, const char
clear_files ();
- while ((next = readdir (reading)) != NULL)
- if (file_interesting (next))
- {
- enum filetype type = unknown;
+ while (1)
+ {
+ /* Set errno to zero so we can distinguish between a readdir failure
+ and when readdir simply finds that there are no more entries. */
+ errno = 0;
+ if ((next = readdir (dirp)) == NULL)
+ {
+ if (errno)
+ {
+ /* Save/restore errno across closedir call. */
+ int e = errno;
+ closedir (dirp);
+ errno = e;
+
+ /* Arrange to give a diagnostic after exiting this loop. */
+ dirp = NULL;
+ }
+ break;
+ }
+
+ if (file_interesting (next))
+ {
+ enum filetype type = unknown;
#if HAVE_STRUCT_DIRENT_D_TYPE
- if (next->d_type == DT_DIR || next->d_type == DT_CHR
- || next->d_type == DT_BLK || next->d_type == DT_SOCK
- || next->d_type == DT_FIFO)
- type = next->d_type;
+ if (next->d_type == DT_DIR || next->d_type == DT_CHR
+ || next->d_type == DT_BLK || next->d_type == DT_SOCK
+ || next->d_type == DT_FIFO)
+ type = next->d_type;
#endif
- total_blocks += gobble_file (next->d_name, type, 0, name);
- }
+ total_blocks += gobble_file (next->d_name, type, 0, name);
+ }
+ }
- if (CLOSEDIR (reading))
+ if (dirp == NULL || CLOSEDIR (dirp))
{
- error (0, errno, "%s", quotearg_colon (name));
+ error (0, errno, _("reading directory %s"), quotearg_colon (name));
exit_status = 1;
/* Don't return; print whatever we got. */
}
Index: remove.c
===================================================================
RCS file: /fetish/cu/src/remove.c,v
retrieving revision 1.59
retrieving revision 1.63
diff -u -p -u -r1.59 -r1.63
--- remove.c 22 Jul 2002 06:59:26 -0000 1.59
+++ remove.c 29 Aug 2002 10:42:12 -0000 1.63
@@ -522,19 +522,30 @@ is_empty_dir (char const *dir)
{
DIR *dirp = opendir (dir);
if (dirp == NULL)
- return false;
+ {
+ closedir (dirp);
+ return false;
+ }
while (1)
{
- struct dirent *dp = readdir (dirp);
+ struct dirent *dp;
const char *f;
+ errno = 0;
+ dp = readdir (dirp);
if (dp == NULL)
- return true;
+ {
+ closedir (dirp);
+ return errno == 0 ? true : false;
+ }
f = dp->d_name;
if ( ! DOT_OR_DOTDOT (f))
- return false;
+ {
+ closedir (dirp);
+ return false;
+ }
}
}
@@ -810,12 +821,27 @@ remove_cwd_entries (char **subdir, struc
while (1)
{
- struct dirent *dp = readdir (dirp);
+ struct dirent *dp;
enum RM_status tmp_status;
const char *f;
- if (dp == NULL)
- break;
+ /* Set errno to zero so we can distinguish between a readdir failure
+ and when readdir simply finds that there are no more entries. */
+ errno = 0;
+ if ((dp = readdir (dirp)) == NULL)
+ {
+ if (errno)
+ {
+ /* Save/restore errno across closedir call. */
+ int e = errno;
+ closedir (dirp);
+ errno = e;
+
+ /* Arrange to give a diagnostic after exiting this loop. */
+ dirp = NULL;
+ }
+ break;
+ }
f = dp->d_name;
if (DOT_OR_DOTDOT (f))
@@ -871,7 +897,13 @@ remove_cwd_entries (char **subdir, struc
break;
}
- closedir (dirp);
+ if (dirp == NULL || CLOSEDIR (dirp) != 0)
+ {
+ /* Note that this diagnostic serves for both readdir
+ and closedir failures. */
+ error (0, errno, _("reading directory %s"), quote (full_filename (".")));
+ status = RM_ERROR;
+ }
return status;
}