summaryrefslogtreecommitdiff
path: root/misc-utils/namei.c
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2009-10-09 16:26:45 +0200
committerKarel Zak <kzak@redhat.com>2009-10-09 16:43:35 +0200
commitc21e7023cac5762d5e3850fc8b02ea481a8d6b44 (patch)
tree3d68a6d68ba2e5bbd178af0894b03eedd1fdb753 /misc-utils/namei.c
parent532c6cb199b926a378079859b3359b50491fa3c6 (diff)
downloadutil-linux-old-c21e7023cac5762d5e3850fc8b02ea481a8d6b44.tar.gz
namei: better mount points detection
Reported-by: Sami Kerola <kerolasa@iki.fi> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/namei.c')
-rw-r--r--misc-utils/namei.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/misc-utils/namei.c b/misc-utils/namei.c
index 94a3c259..f8f096d8 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)) {