I suspect that it'd be very hard to trigger these close failures, but it's better to be safe.
And along the same lines, since there are more way in which fts_close can fail, encourage callers not to ignore its return value. There were four offenders in coreutils, before today. I chose not to make it hard to ignore fts_set, since for many uses, its return value is legitimately ignorable. >From d7702d8443dae6073597f2cc4fa49f85dfeaaed2 Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Tue, 1 Sep 2009 11:18:07 +0200 Subject: [PATCH 1/2] fts: fts_close now fails also when closing a dir file descriptor fails * lib/fts.c (fts_close): Detect close failure, not just fchdir failure, and propagate to caller, along with errno. --- ChangeLog | 4 ++++ lib/fts.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ff10df..89cf0ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2009-09-01 Jim Meyering <meyer...@redhat.com> + fts: fts_close now fails also when closing a dir file descriptor fails + * lib/fts.c (fts_close): Detect close failure, not just fchdir failure, + and propagate to caller, along with errno. + announce-gen: correct formatting in --help output * build-aux/announce-gen (usage): Move the one-line description in --help output "up", to where it belongs, just after Usage:. diff --git a/lib/fts.c b/lib/fts.c index bbcd1ff..a30e38a 100644 --- a/lib/fts.c +++ b/lib/fts.c @@ -606,14 +606,20 @@ fts_close (FTS *sp) if (ISSET(FTS_CWDFD)) { if (0 <= sp->fts_cwd_fd) - close (sp->fts_cwd_fd); + if (close (sp->fts_cwd_fd)) + saved_errno = errno; } else if (!ISSET(FTS_NOCHDIR)) { /* Return to original directory, save errno if necessary. */ if (fchdir(sp->fts_rfd)) saved_errno = errno; - close(sp->fts_rfd); + + /* If close fails, record errno only if saved_errno is zero, + so that we report the probably-more-meaningful fchdir errno. */ + if (close (sp->fts_rfd)) + if (saved_errno == 0) + saved_errno = errno; } fd_ring_clear (&sp->fts_fd_ring); -- 1.6.4.2.384.g5fc62 >From 9b740ea4bcb104eeceb0c847a376d2b7dbb77d1b Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Tue, 1 Sep 2009 11:20:41 +0200 Subject: [PATCH 2/2] fts: help ensure that return values are not ignored * lib/fts_.h (__GNUC_PREREQ): Define. (__attribute_warn_unused_result__): Define. (fts_children, fts_close, fts_open, fts_read): Declare with __attribute_warn_unused_result__. --- ChangeLog | 6 ++++++ lib/fts_.h | 26 ++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89cf0ee..efb2906 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2009-09-01 Jim Meyering <meyer...@redhat.com> + fts: help ensure that return values are not ignored + * lib/fts_.h (__GNUC_PREREQ): Define. + (__attribute_warn_unused_result__): Define. + (fts_children, fts_close, fts_open, fts_read): Declare with + __attribute_warn_unused_result__. + fts: fts_close now fails also when closing a dir file descriptor fails * lib/fts.c (fts_close): Detect close failure, not just fchdir failure, and propagate to caller, along with errno. diff --git a/lib/fts_.h b/lib/fts_.h index ad339ca..0e2d505 100644 --- a/lib/fts_.h +++ b/lib/fts_.h @@ -233,12 +233,30 @@ typedef struct _ftsent { char fts_name[1]; /* file name */ } FTSENT; +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +#if __GNUC_PREREQ (3,4) +# undef __attribute_warn_unused_result__ +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif + __BEGIN_DECLS -FTSENT *fts_children (FTS *, int) __THROW; -int fts_close (FTS *) __THROW; +FTSENT *fts_children (FTS *, int) __THROW __attribute_warn_unused_result__; +int fts_close (FTS *) __THROW __attribute_warn_unused_result__; FTS *fts_open (char * const *, int, - int (*)(const FTSENT **, const FTSENT **)) __THROW; -FTSENT *fts_read (FTS *) __THROW; + int (*)(const FTSENT **, const FTSENT **)) + __THROW __attribute_warn_unused_result__; +FTSENT *fts_read (FTS *) __THROW __attribute_warn_unused_result__; int fts_set (FTS *, FTSENT *, int) __THROW; __END_DECLS -- 1.6.4.2.384.g5fc62