[comp.unix.questions] /bin/pwd

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (09/14/90)

Can anyone tell me how /bin/pwd works?  I thought it was a trivial
program until I tried to write my own without getcwd(3).  getcwd is not
a system call, so it must be possible.  The way I think it works is
quite complicated, so I thought there would be an easier way.

  David Hemmings appeared by permission of the National Forestry Commission.

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/14/90)

In article <2488@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>Can anyone tell me how /bin/pwd works?  I thought it was a trivial
>program until I tried to write my own without getcwd(3).  getcwd is not
>a system call, so it must be possible.  The way I think it works is
>quite complicated, so I thought there would be an easier way.

No, on most systems there is no easier way than the obvious one of
seeing where a succession of ".."s gets you.

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (09/14/90)

In article <13851@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
>In article <2488@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>>Can anyone tell me how /bin/pwd works?  I thought it was a trivial
>>program until I tried to write my own without getcwd(3).  getcwd is not
>>a system call, so it must be possible.  The way I think it works is
>>quite complicated, so I thought there would be an easier way.
>No, on most systems there is no easier way than the obvious one of
>seeing where a succession of ".."s gets you.

That was what I considered "the easy way."  But how do you do that?
For example, how do you find out the name of "."?  You could find out
its inode, and then check the previous directory to see which name
matches its inode; but that only works until you get to the root of the
filesystem your directory is mounted in (I don't mean "/").  What then?  Do
you have to check /etc/mtab?

  I think there should be more race prejudice.  <slap> LESS race prejudice.

cpcahil@virtech.uucp (Conor P. Cahill) (09/14/90)

In article <2488@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>Can anyone tell me how /bin/pwd works?  I thought it was a trivial

On BSD style systems /bin/pwd calls the library function (I think it is 
getcwd(), but don't have the manual nearby).

On System V style systems, getcwd(3) popen(3)'s "/bin/pwd" to get 
the current workind directory.

Anyway, the way pwd works is something like the following:

	Stat the current directory (".") and get the inode number and
		device number

	Open ".." and read each entry
		if you find an entry with the same inode number
			stat it
			if it is the same device number
				you got a match, save name portion
				close this directory
				start again one directory higher
		
		if you don't find an entry with the right inode number
			go back and stat each entry looking for the one
				with the correct device number
		

This goes on and on until you get to the top of the filesystem. (you get
to the top when a stat of . & .. return the exact same stuff.

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/15/90)

In article <2497@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
-In article <13851@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
->No, on most systems there is no easier way than the obvious one of
->seeing where a succession of ".."s gets you.
-That was what I considered "the easy way."  But how do you do that?
-For example, how do you find out the name of "."?  You could find out
-its inode, and then check the previous directory to see which name
-matches its inode; but that only works until you get to the root of the
-filesystem your directory is mounted in (I don't mean "/").  What then?  Do
-you have to check /etc/mtab?

Yes, you got it, exactly.

guy@auspex.auspex.com (Guy Harris) (09/15/90)

>For example, how do you find out the name of "."?  You could find out
>its inode, and then check the previous directory to see which name
>matches its inode; but that only works until you get to the root of the
>filesystem your directory is mounted in (I don't mean "/").  What then?  Do
>you have to check /etc/mtab?

No.  You just have to do a little more work to see which name matches
the inode.

I.e., if the directory whose name you're trying to find, and the
directory in which you're trying to find it, are on the same file
system, *and* you know that the directory entries you get back from
"readdir()" or whatever contain i-numbers (POSIX does *not* guarantee
this, although the SVID and XPG3 do), you can use the i-number from the
directory entry. 

However, if they're *not* on the same file system, for each directory
entry in the directory you're reading you have to construct the path of
the file that entry refers to and "stat()" it (or "lstat()" it, if you
have "lstat()") to find out its inumber; the directory entry's inumber
will be the inumber of the mount point, but the "stat()" will give the
inumber of the file mounted atop that mount point.

guy@auspex.auspex.com (Guy Harris) (09/15/90)

>On System V style systems, getcwd(3) popen(3)'s "/bin/pwd" to get 
>the current workind directory.

On some, anyway.  That's how S5 from AT&T - at least prior to S5R4 -
implements "getcwd()", but you could have "getcwd()" be the routine that
does the work (just like "getwd()", but with bounds checking) and have
"/bin/pwd" just call it.  (SGI basically does that in recent releases,
although "getcwd()" ends up calling a BSD-flavored "getwd()" to do the
actual work).  Dunno whether S5R4 does that or not.

del@thrush.mlb.semi.harris.com (Don Lewis) (09/15/90)

In article <13858@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
>In article <2497@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>-In article <13851@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
>->No, on most systems there is no easier way than the obvious one of
>->seeing where a succession of ".."s gets you.
>-That was what I considered "the easy way."  But how do you do that?
>-For example, how do you find out the name of "."?  You could find out
>-its inode, and then check the previous directory to see which name
>-matches its inode; but that only works until you get to the root of the
>-filesystem your directory is mounted in (I don't mean "/").  What then?  Do
>-you have to check /etc/mtab?
>
>Yes, you got it, exactly.

This scheme fails badly in the presence if Sun's loopback mounts because
the filesystem can be mounted in multiple places.
--
Don "Truck" Lewis                      Harris Semiconductor
Internet:  del@mlb.semi.harris.com     PO Box 883   MS 62A-028
Phone:     (407) 729-5205              Melbourne, FL  32901

cpcahil@virtech.uucp (Conor P. Cahill) (09/15/90)

In article <13858@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes:
>In article <2497@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
>-matches its inode; but that only works until you get to the root of the
>-filesystem your directory is mounted in (I don't mean "/").  What then?  Do
>-you have to check /etc/mtab?
>
>Yes, you got it, exactly.

Actually you can use the device number portion.  (get the device number from
the current directory and then stat each entry in the .. directory looking
for an entry on the same device).


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

toma@ozdaltx.UUCP (Tom Armistead) (09/18/90)

In article <2488@idunno.Princeton.EDU>, pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes:
> Can anyone tell me how /bin/pwd works?  I thought it was a trivial
> program until I tried to write my own without getcwd(3).  getcwd is not
> a system call, so it must be possible.  The way I think it works is
> quite complicated, so I thought there would be an easier way.
> 
>   David Hemmings appeared by permission of the National Forestry Commission.

I don't know how /bin/pwd works - but I ran into the same problem and this
is how I tackled it...

Open "." using stat(2), get the inode number and save it.
Open ".." using stat, get the inode number, if equal to the inode for "." then
	you are at the root dir "/".
If they are not equal:
    open ".." using opendir(3C) and read the entries from it using readdir(3C)
    until you find the inode number for ".", this will give you the name of
    the current dir from the parent.
    Repeat this process walking back to "../..", then "../../..", etc, until
    the 2 inodes are equal...

It sounds kinda messy, but it really isn't after you think about????

I have this coded and working (for System V 3.2), if you would like a copy,
just let me know...

Tom
-- 
-------------------------------
{uunet,smu,ames}!sulaco!ozdaltx!toma      (Tom Armistead @ Garland, Texas)
{mic,void,egsner}!ozdaltx!toma

a0528@gray3.zrz.tu-berlin.de (Ueb28) (09/19/90)

In article <6960@ozdaltx.UUCP> toma@ozdaltx.UUCP (Tom Armistead) writes:

   I don't know how /bin/pwd works - but I ran into the same problem and this
   is how I tackled it...

   Open "." using stat(2), get the inode number and save it.
   Open ".." using stat, get the inode number, if equal to the inode for "." then
	   you are at the root dir "/".
   If they are not equal:
       open ".." using opendir(3C) and read the entries from it using readdir(3C)
[etc.]

It has to be something like that, if not exactly. On a System here
around there is a partition with a scrambled root directory. When you
do a ls -al /expo1, you get:

total 24
drwxrwxrwx  18 root     root         368 Sep  5 20:21 
drwxr-xr-x   5 root     other         80 Jun 23 01:26 386ix
drwx------   3 a0203    101           64 May  2 22:12 a0203
drwxr-xr-x   3 a0238    other         64 Aug 27 10:57 a0238
[etc.]

The first entry is really blank, and there are NO "." and ".." entries.
System works fine, except for users or programs who want to do a pwd
on this partition. pwd answers:

	pwd: cannot open ..

I suggested to patch the first two entries to inode number 2 and the
names "." and "..", but a new Unix release will soon be installed, and
in this turn the partition will be backuped and mkfs'ed.

--
-----------------
Juergen Nickelsen
nickel@w104zrz.zrz.tu-berlin.de
nickelsen@mikroperipherik.e-technik.tu-berlin.dbp.de