On Sun, Oct 04, 2009 at 01:22:19PM +0200, Sami Kerola wrote: > I think I got the patch right now. Yeah, the idea looks better than in the original patch... > Now the only question is do you want to keep is_mountpoint as it is > (generic) or will you like to eliminate extra stat by feeding the > function with stat structure as argument. Personally I favor generic > function, but it's not really my call what will end up to be in use. ... but, I think it's better to re-use already saved 'struct stat'. See my version below. Karel >From c21e7023cac5762d5e3850fc8b02ea481a8d6b44 Mon Sep 17 00:00:00 2001 From: Karel Zak <kzak@xxxxxxxxxx> Date: Fri, 9 Oct 2009 16:26:45 +0200 Subject: [PATCH] namei: better mount points detection Reported-by: Sami Kerola <kerolasa@xxxxxx> Signed-off-by: Karel Zak <kzak@xxxxxxxxxx> --- misc-utils/namei.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 40 insertions(+), 3 deletions(-) diff --git a/misc-utils/namei.c b/misc-utils/namei.c index 94a3c25..f8f096d 100644 --- a/misc-utils/namei.c +++ b/misc-utils/namei.c @@ -61,6 +61,7 @@ struct namei { int relstart; /* offset of relative path in 'abslink' */ struct namei *next; /* next item */ int level; + int mountpoint; /* is mount point */ }; struct idcache { @@ -209,6 +210,31 @@ readlink_to_namei(struct namei *nm, const char *path) nm->abslink[sz] = '\0'; } +static struct stat * +dotdot_stat(const char *dirname, struct stat *st) +{ + char *path; + size_t len; + +#define DOTDOTDIR "/.." + + if (!dirname) + return NULL; + + len = strlen(dirname); + path = malloc(len + sizeof(DOTDOTDIR)); + if (!path) + err(EXIT_FAILURE, _("out of memory?")); + + memcpy(path, dirname, len); + memcpy(path + len, DOTDOTDIR, sizeof(DOTDOTDIR)); + + if (stat(path, st)) + err(EXIT_FAILURE, _("could not stat '%s'"), path); + free(path); + return st; +} + static struct namei * new_namei(struct namei *parent, const char *path, const char *fname, int lev) { @@ -236,6 +262,19 @@ new_namei(struct namei *parent, const char *path, const char *fname, int lev) add_gid(nm->st.st_gid); } + if ((flags & NAMEI_MNTS) && S_ISDIR(nm->st.st_mode)) { + struct stat stbuf, *sb = NULL; + + if (parent && S_ISDIR(parent->st.st_mode)) + sb = &parent->st; + else if (!parent || S_ISLNK(parent->st.st_mode)) + sb = dotdot_stat(path, &stbuf); + + if (sb && (sb->st_dev != nm->st.st_dev || /* different device */ + sb->st_ino == nm->st.st_ino)) /* root directory */ + nm->mountpoint = 1; + } + return nm; } @@ -368,9 +407,7 @@ print_namei(struct namei *nm, char *path) strmode(nm->st.st_mode, md); - if ((flags & NAMEI_MNTS) && prev && - S_ISDIR(nm->st.st_mode) && S_ISDIR(prev->st.st_mode) && - prev->st.st_dev != nm->st.st_dev) + if (nm->mountpoint) md[0] = 'D'; if (!(flags & NAMEI_VERTICAL)) { -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html