Fog Creek Software
Discussion Board




Obtaining File Name from File Pointer in C

ANSI C, for both Linux and Solaris.

I have a file pointer that is passed to a function. This function may be used by several different files.

I would like to be able to get the file name from the file pointer for reporting of errors. All indications and google searches lead me to believe that this is impossible, and the best I can come up with is this function...

char *fname(FILE *stream) {
    static char name[256];
    sprintf(name, "/proc/%d/fd/%d", getpid(), fileno(stream));
    return name;
}

Is there any way I can use the fileno() function to obtain the filename? An inelegant solution I've just thought would be to maintain a table of fileno's and their corresponding filenames. But, if the OS will do this for me, that would be better.

I realize that the best way to do this would be to let the function return an error code so that the calls to the routine calling my function can handle the error. BUT I'd like to have the function report on the file name itself as this routine is called several times and I don't want to junk up my code with several error handling statements.

I would entertain strategies (even if they're in the form of flames at my incompetence) that others have used to handle this problem so that I can do it right the next time.

Shawn Leslie
Tuesday, August 24, 2004

I would venture to say that if you're having trouble finding out how to do it, then it's probably not meant to be done.  There might be some way to do it in a non standard fashion.

How about refactoring the code to take the name as the parameter and then open the file yourself?

;
Tuesday, August 24, 2004

google "GetModuleFileName +Linux".

redguardtoo
Tuesday, August 24, 2004

Can't be done portably.  Just return an error code, and let the piece that knows the filename make the message.

Brian
Tuesday, August 24, 2004

The reason you can't do it sensibly in UNIX is that a "file" on the disk may have multiple names -- due to hard linking.

If you *really* want to do it, on Linux a nice handy way is to wander into /proc/<processnumber>/fd and look at the symbolic link named after the FD you're after looking at. The system "creates" those entries[1] when you open the files, so they're the name you opened it with. I have no idea if /proc is available on Solaris, because I'm a Linux developer and Solaris bites.


[1] Actually, it's not a real filesystem, but the analogy is close enough.

Katie Lucas
Wednesday, August 25, 2004

Remember too, that the underlying descriptor attached to a FILE* might be a device driver or a socket, or the result of calling pipe(), or...

None of which have definitive names in a file system.

(Well, maybe the device driver does, but once you determine major and minor device numbers from the inode, the filesystem is no longer involved.)

David Jones
Wednesday, August 25, 2004

Looks like if I'm doing this, its gonna be a little bit of work... http://www.petergalvin.info/sunworld/1999-swol-04-supersys.html

Shawn Leslie
Wednesday, August 25, 2004

Katie -

Solaris has a /proc filesystem, but the entries in the fd directory aren't symlinks like under linux, but hard links. So you can determine the inode number from /proc and you'll  only be left with the problem of searching for the filename fitting the inode number (presumably using "find" arrrgh!)

  -tim

a2800276
Wednesday, August 25, 2004

Why don't you just make the symlink yourself with symlink(2) [OK, that
was under FreeBSD] and not worry about whether /proc/<pid>/fd contains
links or not?

Your alternative is to try to duplicate what amounts to an internal
kernel function under SysV:  it was called ipath and did the opposite
of the vastly more commonly called namei function.

Thomas E. Kammeyer
Wednesday, August 25, 2004

*  Recent Topics

*  Fog Creek Home