On 06/06/2018 11:37 AM, Stefan Berger wrote:
The dirent's d_type field is not portable to all platforms. So we
have
to use stat() to determine the type of file for the functions that need
to be cross-platform. Fix virFileChownFiles() by calling the new
virFileIsRegular() function.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
---
src/libvirt_private.syms | 1 +
src/util/virfile.c | 17 +++++++++++++----
src/util/virfile.h | 1 +
3 files changed, 15 insertions(+), 4 deletions(-)
+
+bool
+virFileIsRegular(const char *path)
+{
+ struct stat s;
+ return (stat(path, &s) == 0) && S_ISREG(s.st_mode);
This always does a stat.
+}
+
+
/**
* virFileExists: Check for presence of file
* @path: Path of file to check
@@ -3005,12 +3014,13 @@ int virFileChownFiles(const char *name,
return -1;
while ((direrr = virDirRead(dir, &ent, name)) > 0) {
- if (ent->d_type != DT_REG)
- continue;
And this was the non-portable code you're getting rid of, which was
already buggy - even on systems with d_type, a return of DT_UNKNOWN
requires a stat() rather than a blind continue. However, your
replacement is pessimizing platforms where d_type is reliable, by making
us do a stat() where we previously did not need to.
Better would be using macros that use d_type where possible, and fall
back to stat() only when d_type does not exist or is DT_UNKNOWN; for
example, here's how gnulib does it:
#if HAVE_STRUCT_DIRENT_D_TYPE
/* True if the type of the directory entry D is known. */
# define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)
/* True if the type of the directory entry D must be T. */
# define DT_MUST_BE(d, t) ((d)->d_type == (t))
# define D_TYPE(d) ((d)->d_type)
#else
# define DT_IS_KNOWN(d) false
# define DT_MUST_BE(d, t) false
# define D_TYPE(d) DT_UNKNOWN
# undef DT_UNKNOWN
# define DT_UNKNOWN 0
(although we have to be careful with licensing, because that is from
lib/fts.c which is marked GPLv3+).
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization:
qemu.org |
libvirt.org