[Toybox] Add remaining pwd options

Rob Landley rob at landley.net
Sun Jan 13 07:57:28 PST 2013


On 01/13/2013 04:34:56 AM, Felix Janda wrote:
> Sorry for this repeated hair-splitting.

Eh, it happens. :)

I'm constantly mucking about in areas I'm brand new to (or haven't got  
the background for, or last messed with so long ago I've forgotten  
important things, or while massively distracted and sleep deprived...),  
so I'm wrong a lot. I just try to fix it when I notice.

> On 01/12/13 at 11:33pm, Rob Landley wrote:
> > On 01/10/2013 02:25:13 PM, Felix Janda wrote:
> > > On 01/02/13 at 12:41am, Rob Landley wrote:
> > > > What I did was disable #3 in the case where cwd doesn't exist.  
> So
> > > the
> > > > new rule #3 is:
> > > >
> > > > 3) If cwd exists and $PWD doesn't point to it, fall back to -P.
> > >
> > > Thanks for the clarification.
> > >
> > > Your version of 3) depends on whether pwd is builtin or not. Do  
> you
> > > mean
> > > something like "If getcwd() fails ..."?
> >
> > cwd is what getcwd() returns. $PWD is an environment variable.
> 
> I wanted to differentiate between the current working directory and  
> its
> name.

The kernel has two magic symlinks as part of each process's state:

1) "." which is set by chdir() and returned by getcwd().

2) "/" which is set by chroot() and not really returned by anything  
because it's what other paths are explained relative _to_.

Inside the kernel, each points to a dentry, which is pinned by the  
reference so you don't have to worry about it going away. (It can be  
invalidated by deleting the dentry's attached inode, but I believe it's  
still around as a zombie until the reference count drops to zero. And  
there's a horrible magic syscall called switch_root that iterates  
through every process in the system and redirects the "." and "/" links  
of every process from one of these to another, but that does horrible  
latency spike locking.)

Each dentry has a ".." link, which is not a process attribute, but a  
dentry attribute. (Or is it inode? The fact dentries aren't really  
independent of an underlying inode is half the reason you can't  
hardlink directories. Anyway, ".." is implemented by following the  
dentry parent pointer, with the exception that "/" pointing to the  
current dentry is treated the same as the dentry parent pointer being  
NULL. Yes, this means that if you go:

   mkdir("sub");
   chroot("sub");
   chdir("../../../../../../../../..");
   chroot(".");

You can escape a chroot. Moving the "/" symlink _under_ "." means the  
.. test won't hit it, you see. There's no >= test here, just ==.

Anyway, given a dentry the kernel can traverse up to the root (either  
equal to "/" or where the dentry parent pointer is NULL) to work out  
the absolute path to this dentry, and since each dentry only has one  
parent pointer there's only _one_ absolute path to a given dentry.

Does that help?

> Doesn't an unliked current working still exist for the processes
> its the cwd of?

You have a pointer to a zombie dentry, the parent pointer of which is  
NULL. It's been unlinked from the tree but won't be garbage collected  
until the reference count falls to zero. I'd guess the corresponding  
inode has been freed and thus the inode pointer is also NULL (thus  
freeing up actual disk space, unlike a filehandle to an open _file_),  
but I'd have to go look at the kernel source to know for sure.

> (I was wrong about that 3) depends on whether pwd in
> builtin or not since child processes inherit cwd.)

Child processes inherit environment variables too, but a child process  
can't change the parent's attributes. (Ok, it could ptrace it but  
that's HORRIBLE and we're not doing that. Sorry, reflexive action  
anytime anyone, including me, says "you can't do X". There's usually a  
bad way to do it. I have a black belt in bad ways to do things, and a  
lot of experience in cleaning them up to look presentable. I do the  
"don't ask questions, post errors" thing to _myself_ all the time.)

> > > > > BTW, in the case that one has deleted and recreated one's  
> current
> > > > > working
> > > > > directory one could also use "cd ." to get to the new  
> directory.
> > > >
> > > > Good to know. (This means the shell is special casing "." as  
> well as
> > > > "..". I need to read the susv4 shell stuff thoroughly, it's been
> > > > years...)
> > >
> > > The susv4 page special cases "." and ".." a bit, but it seems to  
> me
> > > only
> > > in the $CDPATH handling. Ah, I see that you don't care about  
> $CDPATH
> > > from
> > > the about page.
> >
> > $CDPATH and $PWD are separate.
> 
> I just read
> 
> http://landley.net/toybox/about.html:

I read http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cd.html

(About the above URL: don't ask me why www.opengroup.org redirects to  
pubs.opengroup.org but just opengroup.org says the service is  
discontinued. The safe thing to do is probably just  
http://pubs.opengroup.org/onlinepubs/9699919799/download/ and use a  
file:// url on the local disk. That's what I do most of the time, and  
then have to dig up a public URL when I want to point somebody else at  
a page...)

> > And some things (like $CDPATH support in "cd") await a good  
> explanation
> > of why to bother with them.
> 
> and interpreted it as a reluctance to implement $CDPATH support.

I am reluctant to implement $CDPATH support. Having a search path so  
that when you
"cd frog" it finds /usr/ranunculus/diseases/frog is just _weird_. That  
said, someday an actual user of it might show up and change my mind.

> > > Then I think one can leave out step 5 on susv4's page on
> > > cd, and "cd ." is no more special than "cd dir"; it does a chdir  
> to
> > > "$PWD/."
> > > or "$PWD/dir" respectively and then updates $PWD to its canonical
> > > form. (and
> > > modifies $OLDPWD also if necessary)
> >
> > Um, steps 4 and 8 are the ones that say cd . and .. are special?
> 
> Step 4 means that $CDPATH shouldn't be taken into account when you do
> something like "cd ./dir" or "cd ../dir".

$CDPATH is not the same as $PWD. $CDPATH is a _search_path_ for cd. You  
know how when you run an executable it searches $PATH? Apparently when  
you cd to a directory it searches $CDPATH. Who knew? I didn't, and I've  
been using unix variants since the late 80's. (Well, if you count Vax  
Eunice on my father's work machine which had an amiga software library  
on it and xmodem. If you count _actual_ unix, more like 1992.)

> In Step 8 the usual formal processes of simplifying a path (by  
> removing "."
> dot components and so on) described.
> 
> Of course here "." and ".." are treated specially, but this treatment
> affects only $PWD, since chdir("/some/dir/.") should do the same as
> chdir("/some/dir").

I'm only talking about $PWD.

> Step 9 looks like fun...

I have an epic todo list for toysh. "cd" is a shell command, thus part  
of toysh.

Part of the reason I haven't been dinking at it in small amounts is  
there's so much context to keeps traight in your head I should probably  
buckle down and focus on just the shell for a couple months at some  
point, and right now the same effort completes multiple smaller  
commands.

That said, I should do the basic cleanup pass (remove toybuf dependency  
that imposes command line length limitations), add basic environment  
variable support, start on conditionals (if/while/for)...

But I need to finish the cleanup pass on cp. And finish the  
losetup/umount/mount chain. And review the pile of commands that are  
already in but not properly cleaned up. And figure out why current  
toolchains stopped doing proper dead function elimination (a toybox  
with just "true" on x86-64 is 15k! That's ridiculous. Admittedly a  
main() that does nothing but "return 1", built with -s -Os is 6k.  
That's gcc+glibc for you. But still, that extra 9k is sad. And if you  
objdump -d a toybox built with gcc 4.2.1 it hasn't got parse_optflags()  
in it, but one built with ubuntu's current gcc does. Yup, upstream  
toolchain regression in the ability to eliminiate dead code. The  
<strike>aristocrats</strike> free software foundation!

Rob
 1358092648.0


More information about the Toybox mailing list