I've rewritten virFileLinkPointsTo to be a lot simpler, and more importantly, it has far fewer failure points. If anyone wants to preserve the original behavior that makes it fail when the first parameter does not specify a symlink, I can add that. The only difference in behavior would be when the two files are hard-linked. In any case, I'll remove the FIXME comment. The diff below is not very readable. Bottom line, it replaces a pair of functions (the latter is a stub for mingw) with this: #define SAME_INODE(Stat_buf_1, Stat_buf_2) \ ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \ && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev) int virFileLinkPointsTo(const char *checkLink, const char *checkDest) { struct stat src_sb; struct stat dest_sb; if (stat (checkLink, &src_sb) || stat (checkDest, &dest_sb)) return 0; /* FIXME: if required, lstat checkLink to ensure it's a symlink */ if (! SAME_INODE (src_sb, dest_sb)) { virLog("Link '%s' does not point to '%s', ignoring\n", checkLink, checkDest); return 0; } return 1; } >From 4e70c02e547b078b8f35afd0996b6887e1593afd Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyering@xxxxxxxxxx> Date: Tue, 12 Aug 2008 19:07:46 +0200 Subject: [PATCH] rewrite virFileLinkPointsTo * src/util.c (SAME_INODE): Define. (virFileLinkPointsTo): Rewrite to be more portable and more efficient. --- src/util.c | 97 ++++++----------------------------------------------------- 1 files changed, 10 insertions(+), 87 deletions(-) diff --git a/src/util.c b/src/util.c index 9f056e0..2905a0a 100644 --- a/src/util.c +++ b/src/util.c @@ -397,107 +397,30 @@ int virFileHasSuffix(const char *str, return STREQ(str + len - suffixlen, suffix); } -#ifndef __MINGW32__ +#define SAME_INODE(Stat_buf_1, Stat_buf_2) \ + ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \ + && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev) int virFileLinkPointsTo(const char *checkLink, const char *checkDest) { - char dest[PATH_MAX]; - char real[PATH_MAX]; - char checkReal[PATH_MAX]; - int n; - - /* read the link destination */ - if ((n = readlink(checkLink, dest, PATH_MAX)) < 0) { - switch (errno) { - case ENOENT: - case ENOTDIR: - return 0; - - case EINVAL: - virLog("File '%s' is not a symlink\n", - checkLink); - return 0; - - } - virLog("Failed to read symlink '%s': %s\n", - checkLink, strerror(errno)); - return 0; - } else if (n >= PATH_MAX) { - virLog("Symlink '%s' contents too long to fit in buffer\n", - checkLink); - return 0; - } + struct stat src_sb; + struct stat dest_sb; - dest[n] = '\0'; + if (stat (checkLink, &src_sb) || stat (checkDest, &dest_sb)) + return 0; - /* make absolute */ - if (dest[0] != '/') { - char dir[PATH_MAX]; - char tmp[PATH_MAX]; - char *p; + /* FIXME: if required, lstat checkLink to ensure it's a symlink */ - strncpy(dir, checkLink, PATH_MAX); - dir[PATH_MAX-1] = '\0'; - - if (!(p = strrchr(dir, '/'))) { - virLog("Symlink path '%s' is not absolute\n", checkLink); - return 0; - } - - if (p == dir) /* handle unlikely root dir case */ - p++; - - *p = '\0'; - - if (virFileBuildPath(dir, dest, NULL, tmp, PATH_MAX) < 0) { - virLog("Path '%s/%s' is too long\n", dir, dest); - return 0; - } - - strncpy(dest, tmp, PATH_MAX); - dest[PATH_MAX-1] = '\0'; - } - - /* canonicalize both paths */ - if (!realpath(dest, real)) { - virLog("Failed to expand path '%s' :%s\n", dest, strerror(errno)); - strncpy(real, dest, PATH_MAX); - real[PATH_MAX-1] = '\0'; - } - - if (!realpath(checkDest, checkReal)) { - virLog("Failed to expand path '%s' :%s\n", checkDest, strerror(errno)); - strncpy(checkReal, checkDest, PATH_MAX); - checkReal[PATH_MAX-1] = '\0'; - } - - /* compare */ - if (STRNEQ(checkReal, real)) { + if (! SAME_INODE (src_sb, dest_sb)) { virLog("Link '%s' does not point to '%s', ignoring\n", - checkLink, checkReal); + checkLink, checkDest); return 0; } return 1; } -#else /* !__MINGW32__ */ - -/* Gnulib has an implementation of readlink which could be used - * to implement this, but it requires LGPLv3. - */ - -int -virFileLinkPointsTo (const char *checkLink ATTRIBUTE_UNUSED, - const char *checkDest ATTRIBUTE_UNUSED) -{ - virLog (_("%s: not implemented\n"), __FUNCTION__); - return 0; -} - -#endif /*! __MINGW32__ */ - int virFileExists(const char *path) { struct stat st; -- 1.6.0.rc2.38.g413e06 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list