[comp.unix.questions] How can I get file name from a file descriptor?

Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) (08/16/89)

Folks,

If I hold the descriptor to a file, how can I find out the name of the file it points to?

Thanks...

Nagesh
716-427-5458 / 5257

gwyn@smoke.BRL.MIL (Doug Gwyn) (08/16/89)

In article <20614@adm.BRL.MIL> Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) writes:
>If I hold the descriptor to a file, how can I find out the name of the file it points to?

There need not be any name associated with the descriptor,
or there may be several possible names by which one could
access the same object.  It sounds like you're trying to
solve the wrong problem..

jrw@mtune.ATT.COM (Jim Webb) (08/24/89)

In article <20614@adm.BRL.MIL>, Pabbisetty.henr@xerox.com (Nagesh Pabbisetty) writes:
> If I hold the descriptor to a file, how can I find out the name
> of the file it points to?

Using System V:

You can use the fstat() call to grab the stat structure of the file.
This struture has a couple fields of interest, st_dev and st_ino, the device
and inode of the file respectively.  The st_dev is a pointer to the
disk device that the inode resides on, and is actually made up from
the major and minor numbers.

So, lets say we do the following:

	#include <sys/types.h>
	#include <sys/stat.h>

	struct stat statbuf;

	fstat(fd,&statbuf)

We now have the device of the file in statbuf.st_dev and the inode number
in statbuf.st_ino. 

We now need to get the filesystem associated with that device.

We can do this by looking thru /etc/mnttab.  /etc/mnttab contains
the filesystem name and the name of the device it is mounted on.
So, what we need to do is look at each device name, and compare
the major/minor number of it to the st_dev info we got above.
The major/minor numbers are stored in st_rdev when we are dealing
with a device file.

When we find a match, we have the starting point of the filesystem
that the file in question is on.

So....  /etc/mnttab has a specific format, and it is described
in mnttab.h.  Two of the fields are of interest here, mt_dev,
which is the name of the device, and mt_filsys, which is the
name of the mountpoint.

	#include <fcntl.h>
	#include <mnttab.h>

	struct mnttab mntbuf;
	struct stat mntstat;
	int mntfd, foundit=0;

	mntfd=open("/etc/mnttab",O_RDONLY);

	while (read(mntfd,&mntbuf,sizeof struct mnttab)>0)
	{

		stat(mntbuf.mt_dev,&mntstat);        /* the device */
	
		if (mntstat.st_rdev==statbuf.st_dev) /* from first fstat */
		{
			foundit++;                   /* found a match */
			break;
		}
	}


Ok, now assuming we foundit, we have in mntbuf.st_filsys the name
of the mountpoint of the filesystem, eg /usr or /b1 or /usr/src or
whatever.

Now, the fun really begins :-)  We need to traverse this directory
tree and find the file with the inode we got at the very beginning
of this exercise.

We can cheat, and use the find command and popen() function:

		char findcmd[1024];
		FILE *findfp;
	
		sprintf(findcmd,"find %s -inum %d -print",mntbuf.mt_filsys,
				atoi(statbuf.st_ino));

		findfp=popen(findcmd,"r");

Now, whatever we read from findfp will be the name(s) of the file that is
associated with the file descriptor we had all the way at the
top of this mess :-)  Be prepared for a LONG wait if the filesystem
is of any size.  Also, if there are links to the file, you will get
all of the names from the find command.

I hope this makes sense....and works, for that matter, too :-)  Any
comments on coding style >/dev/null, please...  

-- 
Jim Webb                "Out of Phase -- Get Help"               att!mtune!jrw
#include <std/disclaimer.h>                                  jrw@mtune.att.com