[Toybox] Add remaining pwd options

Rob Landley rob at landley.net
Sat Dec 29 22:53:01 PST 2012


On 12/29/2012 07:38:24 AM, Felix Janda wrote:
> On 12/29/12 at 03:53am, Rob Landley wrote:
> > On 12/28/2012 03:24:17 PM, Felix Janda wrote:
> > > Hi,
> > >
> > > the first patch adds the -L and -P options to pwd as specified by
> > > POSIX.
> > > The test script again uses stat. This time in order to get inode
> > > numbers
> > > of directories.
> >
> > For future reference adding the test in the same commit as the  
> changes
> > being tested is probably ok.
> 
> Ok.
> 
> > I've applied this patch, but am going to have to take a closer look  
> at
> > it in the morning. (You added a -L option which... is a NOP? Huh,  
> what
> > posix specifies here is kind of insane, there's no way to get the  
> raw
> > getcwd() output. The -L stuff is all about $PWD, and if that doesn't
> > have a valid value it falls back to -P which does a realpath() on  
> the
> > data to strip symlinks...? I need to read this when I'm more awake,
> > this standard is written for a system that stores state different  
> than
> > linux. The current working directory is a process attribute used
> > directly by the vfs, it's not an environment variable...)
> >
> > I think the fix is to have -L _not_ be the default, and to have pwd
> > return the raw getcwd() output when neither -L nor -P is  
> specified...
> > but that's a technical violation of posix...
> 
> POSIX says that "pwd" should behave the same as "pwd -L".

Posix seems to believe that the PWD environment variable is where the  
current directory is stored, which is not how Linux works. On linux,  
getcwd() returns one of two process-specific vfs attributes (chdir()  
sets "." and chroot() sets "/", and neither of those is an environment  
variable). If you "export PWD=/blah" that's not the same as calling  
chdir.

> The current
> "pwd -P" should behave the same way as the previous version of "pwd".  
> It
> just returns the getcwd() output.

Which is always an abspath. (I checked.)

I think what happens when you cd through a symlink is that the shell  
saves the path you descended into in $PWD, and then if you cd ".." it  
chops off the last path component instead of actually dereferencing ..  
(which would wind up somewhere other than the directory you came from).

So pwd -L is showing you the shell's view of things (using the $PWD  
environment variable), and pwd -P is showing you the realpath(). And  
what this basically means is "pwd is more or less a shell builtin", the  
standard just isn't EXPLAINING it clearly.

> "pwd -L" does just check whether the
> environment variable PWD is also a valid current working directory and
> uses that instead of the output of getcwd() if that's the case.

Posix goes on at some length about no "." or ".." in it. I added logic  
to do this, but haven't checked it in yet.

> So according to POSIX we have:
> 
> $ cd /tmp
> $ ln -s . a
> $ cd a
> $ export PWD=/tmp/a
> $ pwd
> /tmp/a
> $ pwd -P
> /tmp
> 
> Actually at least bash seems to update PWD automatically so that the  
> export
> statement is unnecessary.

Indeed, bash updates PWD. (Unless you assign it to something else or  
unset it.)

> It's maybe interesting to see what coreutils is doing. A fragment:

I never look at gnu source if I can avoid it. I sometimes run that  
stuff under strace, but mostly I just read the docs and work out tests.

>   /* POSIX requires a default of -L, but most scripts expect -P.  */
>   bool logical = (getenv ("POSIXLY_CORRECT") != NULL);

The rule is "Anything gnu does is a bad idea", and there are about as  
many exceptions to that as any other rule.

I think I understand _why_ -L is doing that, and the sanity checks are  
so if somebody tries to futz around with pwd to point somewhere else  
(or in a way the shell wouldn't have set it), we discard it and give  
the abspath instead for security-ish reasons. But the user friendly  
path may have $HOME be a symlink with the abspath on /mnt/vol2 or  
something, and we want to default to giving the PWD the user actually  
remembers.

> The implementation of "pwd -L" could also use realpath instead of  
> stat.

Stat's easier.

> Taking a further look at POSIX I think that the option string should  
> be
> ">0LP[-LP]" instead of ">0LP[!LP]".

I already made that change locally. :)

> Felix
> 
> > Rob
> 

Rob
 1356850381.0


More information about the Toybox mailing list