[elbe-devel] [PATCH] filesystem: make Filesyste.realpath() handle absolute paths in links

Torben Hohn torben.hohn at linutronix.de
Tue Jun 18 09:22:10 CEST 2019


On Mon, Jun 17, 2019 at 06:43:45PM +0200, Olivier Dion wrote:
> I've wrote a dozen of cases .. It cover them all .. I hope it does for
> you too.  Commit is pushed on devel/dion/issue-199
> 
> 
> Signed-off-by: Olivier Dion <dion at linutronix.de>

ok. this looks good.

please fold it with 
f035d693386c ("Add 'realpath' method to 'Filesystem'")

and add 

Reviewed-by: Torben Hohn <torben.hohn at linutronix.de>

then rebase onto master, and send me a pull request.
Thanks a lot for this work.

> ---
>  elbepack/filesystem.py | 44 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 34 insertions(+), 10 deletions(-)
> 
> diff --git a/elbepack/filesystem.py b/elbepack/filesystem.py
> index 4c925d1c..450f1524 100644
> --- a/elbepack/filesystem.py
> +++ b/elbepack/filesystem.py
> @@ -85,26 +85,50 @@ class Filesystem(object):
>          os.makedirs(self.fname(path))
>  
>      def realpath(self, path):
> -        if path[0] != os.sep:
> -            path = os.sep + path
> +
>          path = path.split(os.sep)
>          path.reverse()
> +        following = []
>          real_path = [self.path]
> +
>          while path:
>              candidate = path.pop()
> +
> +            # Don't care
>              if candidate == '' or candidate == os.curdir:
>                  continue
> -            elif candidate == os.pardir:
> +
> +            # Can't go out of RFS
> +            if candidate == os.pardir:
> +                if following:
> +                    following.pop()
>                  if len(real_path) > 1:
>                      real_path.pop()
> -            else:
> +                continue
> +
> +            parent = os.sep.join(real_path)
> +            new_path = os.path.join(parent, candidate)
> +            if not os.path.islink(new_path):
> +                if following:
> +                    following.pop()
>                  real_path.append(candidate)
> -                new_path = os.sep.join(real_path)
> -                if os.path.islink(new_path):
> -                    elements = os.readlink(new_path)
> -                    for element in reversed(elements.split(os.sep)):
> -                        path.append(element)
> -                    real_path.pop()
> +                continue
> +
> +            # Circular loop; Don't follow it
> +            if new_path in following:
> +                real_path.append(candidate)
> +                continue
> +
> +            following.append(new_path)
> +            link = os.readlink(new_path)
> +
> +            # Reset root for absolute link
> +            if os.path.isabs(link):
> +                real_path = [self.path]
> +
> +            for element in reversed(link.split(os.sep)):
> +                path.append(element)
> +
>          return os.sep.join(real_path)
>  
>      def symlink(self, src, path, allow_exists=False):
> -- 
> 2.11.0Signed-off-by: Olivier Dion <dion at linutronix.de>
> ---
>  elbepack/filesystem.py | 44 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 34 insertions(+), 10 deletions(-)
> 
> diff --git a/elbepack/filesystem.py b/elbepack/filesystem.py
> index 4c925d1c..450f1524 100644
> --- a/elbepack/filesystem.py
> +++ b/elbepack/filesystem.py
> @@ -85,26 +85,50 @@ class Filesystem(object):
>          os.makedirs(self.fname(path))
>  
>      def realpath(self, path):
> -        if path[0] != os.sep:
> -            path = os.sep + path
> +
>          path = path.split(os.sep)
>          path.reverse()
> +        following = []
>          real_path = [self.path]
> +
>          while path:
>              candidate = path.pop()
> +
> +            # Don't care
>              if candidate == '' or candidate == os.curdir:
>                  continue
> -            elif candidate == os.pardir:
> +
> +            # Can't go out of RFS
> +            if candidate == os.pardir:
> +                if following:
> +                    following.pop()
>                  if len(real_path) > 1:
>                      real_path.pop()
> -            else:
> +                continue
> +
> +            parent = os.sep.join(real_path)
> +            new_path = os.path.join(parent, candidate)
> +            if not os.path.islink(new_path):
> +                if following:
> +                    following.pop()
>                  real_path.append(candidate)
> -                new_path = os.sep.join(real_path)
> -                if os.path.islink(new_path):
> -                    elements = os.readlink(new_path)
> -                    for element in reversed(elements.split(os.sep)):
> -                        path.append(element)
> -                    real_path.pop()
> +                continue
> +
> +            # Circular loop; Don't follow it
> +            if new_path in following:
> +                real_path.append(candidate)
> +                continue
> +
> +            following.append(new_path)
> +            link = os.readlink(new_path)
> +
> +            # Reset root for absolute link
> +            if os.path.isabs(link):
> +                real_path = [self.path]
> +
> +            for element in reversed(link.split(os.sep)):
> +                path.append(element)
> +
>          return os.sep.join(real_path)
>  
>      def symlink(self, src, path, allow_exists=False):
> -- 
> 2.11.0
> 
> On 2019-06-14T17:29:35+0200, Torben Hohn wrote:
> 
> > the realpath() implementation is still not correct.
> > but i like the approach.
> 
> > please finish it. and fold my patch into it.
> 
> 
> 
> > On Fri, Jun 14, 2019 at 05:28:04PM +0200, Torben Hohn wrote:
> > > the current implementation fails for absolute links:
> > > 
> > > >>> from elbepack import filesystem
> > > >>> f = filesystem.Filesystem('xxx')
> > > >>> f.mkdir_p('/usr/bin')
> > > >>> f.symlink('/usr/bin/vim', '/usr/bin/omg')
> > > >>> f.realpath('/usr/bin/omg')
> > > '/home/torbenh/elbe/elbe/xxx/usr/bin/usr/bin/vim'
> > > >>>
> > > 
> > > handle it by "initialising" path again, when an absolute path
> > > is returned from os.readlink()
> > > 
> > > this still lacks catching recursive links, and i think, that .. is
> > > not evaluated properly in any case.
> > > 
> > > Signed-off-by: Torben Hohn <torben.hohn at linutronix.de>
> > > ---
> > >  elbepack/filesystem.py | 11 ++++++++---
> > >  1 file changed, 8 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/elbepack/filesystem.py b/elbepack/filesystem.py
> > > index 4c925d1c6..91dbe0879 100644
> > > --- a/elbepack/filesystem.py
> > > +++ b/elbepack/filesystem.py
> > > @@ -102,9 +102,14 @@ class Filesystem(object):
> > >                  new_path = os.sep.join(real_path)
> > >                  if os.path.islink(new_path):
> > >                      elements = os.readlink(new_path)
> > > -                    for element in reversed(elements.split(os.sep)):
> > > -                        path.append(element)
> > > -                    real_path.pop()
> > > +                    if os.path.isabs(elements):
> > > +                        path = elements.split(os.sep)
> > > +                        path.reverse()
> > > +                        real_path = [self.path]
> > > +                    else:
> > > +                        for element in reversed(elements.split(os.sep)):
> > > +                            path.append(element)
> > > +                        real_path.pop()
> > >          return os.sep.join(real_path)
> > >  
> > >      def symlink(self, src, path, allow_exists=False):
> > > -- 
> > > 2.11.0
> > > 
> > > 
> > > _______________________________________________
> > > elbe-devel mailing list
> > > elbe-devel at linutronix.de
> > > https://lists.linutronix.de/mailman/listinfo/elbe-devel
> 
> > -- 
> > Torben Hohn
> > Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen
> > Phone: +49 7556 25 999 18; Fax.: +49 7556 25 999 99
> 
> > Hinweise zum Datenschutz finden Sie hier (Informations on data privacy 
> > can be found here): https://linutronix.de/kontakt/Datenschutz.php
> 
> > Linutronix GmbH | Firmensitz (Registered Office): Uhldingen-Mühlhofen | 
> > Registergericht (Registration Court): Amtsgericht Freiburg i.Br., HRB700 
> > 806 | Geschäftsführer (Managing Directors): Heinz Egger, Thomas Gleixner
> 
> 
> -- 
> Olivier Dion
> Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen

-- 
Torben Hohn
Linutronix GmbH | Bahnhofstrasse 3 | D-88690 Uhldingen-Mühlhofen
Phone: +49 7556 25 999 18; Fax.: +49 7556 25 999 99

Hinweise zum Datenschutz finden Sie hier (Informations on data privacy 
can be found here): https://linutronix.de/kontakt/Datenschutz.php

Linutronix GmbH | Firmensitz (Registered Office): Uhldingen-Mühlhofen | 
Registergericht (Registration Court): Amtsgericht Freiburg i.Br., HRB700 
806 | Geschäftsführer (Managing Directors): Heinz Egger, Thomas Gleixner



More information about the elbe-devel mailing list