On Tue, Jul 28, 2009 at 15:21, Karel Zak <kzak@xxxxxxxxxx> wrote: > On Tue, Jul 28, 2009 at 01:11:11PM +0200, Sami Kerola wrote: >> On Mon, Jul 27, 2009 at 14:13, Sami Kerola<kerolasa@xxxxxx> wrote: >> >> The only way I could think of making mount point detection work >> correctly is to stat current inode and and .. in same directory, > > Right. > >> compare device numbers and if they differ it's a mount point. In case >> device number is the same and inode then it must be root. A better >> patch will follow later, or much later. > > OK, thanks. I think I got the patch right now. 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. -- Sami Kerola http://www.iki.fi/kerolasa/
From 02739d576ee7a79913225bc8ab31eb0d4b33524a Mon Sep 17 00:00:00 2001 From: Sami Kerola <kerolasa@xxxxxx> Date: Sun, 4 Oct 2009 13:07:10 +0200 Subject: [PATCH] namei: mount points Cc: kerolasa@xxxxxx Signed-off-by: Sami Kerola <kerolasa@xxxxxx> --- misc-utils/namei.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 files changed, 39 insertions(+), 3 deletions(-) diff --git a/misc-utils/namei.c b/misc-utils/namei.c index b8930cd..9cb5b2d 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 { @@ -208,6 +209,41 @@ readlink_to_namei(struct namei *nm, const char *path) nm->abslink[sz] = '\0'; } +int is_mountpoint(const char *input_path) +{ + struct stat input_stat; + struct stat dotdot_stat; + char *dotdot_path; + /* Good default; most are not. */ + int return_value = 0; + + lstat(input_path, &input_stat); + if (!(S_ISDIR(input_stat.st_mode))) { + /* Only directories can be mount points. */ + return(return_value); + } + + /* Append to original directory /.. and stat that. + * Assumptation that you could chop last directory and + * stat that one works only if paths are always absolute. */ + dotdot_path = malloc(strlen(input_path) + 4); + dotdot_path[0] = '\0'; + strcat(dotdot_path, input_path); + strcat(dotdot_path, "/.."); + stat(dotdot_path, &dotdot_stat); + + if (input_stat.st_dev != dotdot_stat.st_dev) { + /* Different device; must be mount point. */ + return_value = 1; + } else if (input_stat.st_ino == dotdot_stat.st_ino) { + /* Same device, same inode; must be root */ + return_value = 1; + } + + free(dotdot_path); + return(return_value); +} + static struct namei * new_namei(struct namei *parent, const char *path, const char *fname, int lev) { @@ -227,6 +263,8 @@ new_namei(struct namei *parent, const char *path, const char *fname, int lev) err(EXIT_FAILURE, _("out of memory?")); if (lstat(path, &nm->st) == -1) err(EXIT_FAILURE, _("could not stat '%s'"), path); + if (flags & NAMEI_MNTS) + nm->mountpoint = is_mountpoint(path); return nm; } @@ -365,9 +403,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 ((flags & NAMEI_MNTS) && nm->mountpoint) md[0] = 'D'; if (!(flags & NAMEI_VERTICAL)) { -- 1.6.4.4