Getting a File Name from a FILE *

D

Dale Pennington

I find myself in the odd situation of trying to determine the name of a file
that has been opened somewhere else with an fopen call, so all I have is the
FILE * from that fopen call. I perused my favorite online C API reference
and did not find a method, but hopefully that means I did not look in the
right places (we all know how easy it is to find stuff once you know where
to acutally look).

So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

Thanks for the assist,
Dale Pennington
 
S

sjdevnull

Dale said:
So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

No.

A FILE * may have many names/paths in the filesystem that refer to the
underlying file, or none at all, and there's no way in standard C to go
from a FILE * to a list of zero or more filenames that correspond to
it.

offtopic: Depending on your platform and needs, you might look at
something like lsof if you really need to do this. You're really best
off eliminating the need, though.
 
E

Eric Sosman

Dale Pennington wrote On 08/22/06 17:14,:
I find myself in the odd situation of trying to determine the name of a file
that has been opened somewhere else with an fopen call, so all I have is the
FILE * from that fopen call. I perused my favorite online C API reference
and did not find a method, but hopefully that means I did not look in the
right places (we all know how easy it is to find stuff once you know where
to acutally look).

So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

This is Question 19.15 in the comp.lang.c Frequently
Asked Questions (FAQ) list

http://www.c-faq.com/

.... and you're not going to like the answer. :-(
 
B

Ben Pfaff

Dale Pennington said:
So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

This is a FAQ.

19.15: How can I recover the file name given an open stream or file
descriptor?

A: This problem is, in general, insoluble. Under Unix, for
instance, a scan of the entire disk (perhaps involving special
permissions) would theoretically be required, and would fail if
the descriptor were connected to a pipe or referred to a deleted
file (and could give a misleading answer for a file with
multiple links). It is best to remember the names of files
yourself as you open them (perhaps with a wrapper function
around fopen()).
 
M

Martin Ambuhl

Dale said:
I find myself in the odd situation of trying to determine the name of a file
that has been opened somewhere else with an fopen call, so all I have is the
FILE * from that fopen call. I perused my favorite online C API reference
and did not find a method, but hopefully that means I did not look in the
right places (we all know how easy it is to find stuff once you know where
to acutally look).

So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

Save it yourself when it is opened. There is no standard way to recover
such information. If your program managed to fopen() the file, then you
already have the information.
 
K

Keith Thompson

Martin Ambuhl said:
Save it yourself when it is opened. There is no standard way to
recover such information. If your program managed to fopen() the
file, then you already have the information.

That's correct (some systems *might* provide some non-portable way to
get this information, but as far as I know many systems don't.)

But the obvious solution, remembering the name when you call fopen(),
isn't always a possibility. Programs are not always monolithic; the
code that calls fopen() might have been written by someone else, and
you might not be able to modify it.

It wouldn't have been entirely nonsensical for the C standard to have
specified, say, an fname() function that returns a pointer to a copy
of the string that was passed to fopen(), or perhaps to some canonical
representation. The behavior for stdin, stdout, and stderr, and for
streams not opened with fopen(), would have to be defined, but that
wouldn't be an insurmountable problem. Such a thing might have been
useful, and it exists in at least one non-C language that I know of.

In C, it doesn't exist because it doesn't exist. If you can, remember
the name when you open the file. If you can't do that, try to figure
out a way to avoid the requirement in the first place.
 
E

Eric Sosman

Keith said:
[...]
It wouldn't have been entirely nonsensical for the C standard to have
specified, say, an fname() function that returns a pointer to a copy
of the string that was passed to fopen(), or perhaps to some canonical
representation. [...]

Clearly, fname() would have to be allowed to fail, possibly
by returning NULL. This would leave the O.P. in the uncomfortable
situation of having a function that might solve his problem, but
might also just throw up its hands and leave his situation unimproved.

But let's suppose an fopen() that squirrels away a copy of its
first argument for later use by fname(). Such an fopen() would need
to be able to fail for lack of enough memory to stash the filename
string, even if the program never intended to call fname() and the
string would never be used. ("ECATCH22: insufficient unnecessary
memory.") Bummer!

Finally, systems capable of running multiple programs at the same
time exist, and though simultaneity is not "officially recognized" by
the C Standard, it must nonetheless be acknowledged. The file name
with which fopen() successfully opened a file, even if saved verbatim,
might no longer be valid when fname() is called, or might even lead
to a completely different file. (Some security exploits have relied
on exactly this situation.)

Putting all this together, I'd still agree that "it wouldn't have
been entirely nonsensical" to specify fname(). I cannot believe,
though, that it would have been entirely sensical.
 
C

CBFalconer

Eric said:
.... snip ...

But let's suppose an fopen() that squirrels away a copy of its
first argument for later use by fname(). Such an fopen() would need
to be able to fail for lack of enough memory to stash the filename
string, even if the program never intended to call fname() and the
string would never be used. ("ECATCH22: insufficient unnecessary
memory.") Bummer!

No, all it has to do is squirrel away a NULL with which to answer
any future fname call. Then only the fname fails.
 
W

William Hughes

Eric said:
Keith said:
[...]
It wouldn't have been entirely nonsensical for the C standard to have
specified, say, an fname() function that returns a pointer to a copy
of the string that was passed to fopen(), or perhaps to some canonical
representation. [...]

Clearly, fname() would have to be allowed to fail, possibly
by returning NULL. This would leave the O.P. in the uncomfortable
situation of having a function that might solve his problem, but
might also just throw up its hands and leave his situation unimproved.

But this is frequently the case with C functions. This is QOI.
But let's suppose an fopen() that squirrels away a copy of its
first argument for later use by fname(). Such an fopen() would need
to be able to fail for lack of enough memory to stash the filename
string, even if the program never intended to call fname() and the
string would never be used. ("ECATCH22: insufficient unnecessary
memory.") Bummer!

Doesn't seem to be a major problem. Add one byte to the minimum
requirement, and use this to signal the memory problem to fname.
fopen() would not fail, fname() would.
Finally, systems capable of running multiple programs at the same
time exist, and though simultaneity is not "officially recognized" by
the C Standard, it must nonetheless be acknowledged. The file name
with which fopen() successfully opened a file, even if saved verbatim,
might no longer be valid when fname() is called, or might even lead
to a completely different file. (Some security exploits have relied
on exactly this situation.)

This can happen without needing multiple programs.
We have that fopen(fname(fp)) might not succeed, or might not point
to the same file as fp. I don't however see a security hole. fname()
should return only a string, so if this string refers to a file that
the
program does not have permission to open the fopen(fname(fp)) should
fail.
The fact that a previous fopen() to the same string succeeded
should not influence things.
Putting all this together, I'd still agree that "it wouldn't have
been entirely nonsensical" to specify fname(). I cannot believe,
though, that it would have been entirely sensical.

I disagree.

-William Hughes
 
B

Bill Pursell

Dale said:
I find myself in the odd situation of trying to determine the name of a file
that has been opened somewhere else with an fopen call, so all I have is the
FILE * from that fopen call. I perused my favorite online C API reference
and did not find a method, but hopefully that means I did not look in the
right places (we all know how easy it is to find stuff once you know where
to acutally look).

So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

Out of curiousity, why the need? As others have pointed out, it's
not going to be easy, and removing the need is probably your
best solution. I ask because I can remember long ago thinking
that I had that exact same need, and found that it wasn't really
the name I needed but some other piece of information which
I thought was only attainable from the name (eg a mount point,
or a new FILE *). Presently, the only time I ever need the name
is immediately after fopen, and I only use it for use in printing
the log message that fopen() failed. Occasionally I'll hold onto
the name to log an ferror(), but I'm happy logging a nameless
message as well, since it's usually pretty easy for the reader
of the message to deduce the problem without the filename.
(eg, if the read() caused an error, it's because the
mount failed, and has nothing to do with a particular file.
Having the pathname in the log message might help discover
the failing disk, but that's usually obvious from other sources.)
 
K

Kenneth Brody

Bill said:
Dale said:
I find myself in the odd situation of trying to determine the name of a file
that has been opened somewhere else with an fopen call, so all I have is the [...]
So, the question, given a FILE *, can one get back to the name/path of the
file that was opened, and if so, how ?

Out of curiousity, why the need?
[...]

I wrote a wrapper around fopen/fclose (as well as the POSIX open and
close functions) to store the filename. Should some error occur later
on while accessing the file, the filename can be included in the error
message. (The filename is used internally for some other things as
well, but error messages are the main reason.)

Yes, this is an admittedly limited case, but I think it's a perfectly
valid example of "why the need?" And, should an error occur on
something other than one of the files opened by the wrappers, then the
error simply doesn't display the filename.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
R

Richard Bos

Keith Thompson said:
It wouldn't have been entirely nonsensical for the C standard to have
specified, say, an fname() function that returns a pointer to a copy
of the string that was passed to fopen(), or perhaps to some canonical
representation. The behavior for stdin, stdout, and stderr, and for
streams not opened with fopen(), would have to be defined, but that
wouldn't be an insurmountable problem. Such a thing might have been
useful, and it exists in at least one non-C language that I know of.

Then that non-C language is misleading in some cases. It is possible
under some OSes to delete a file from a directory while a program has it
opened. If the FILE were to remember the original name, that name would
then be wrong.

Richard
 
C

CBFalconer

Richard said:
Then that non-C language is misleading in some cases. It is possible
under some OSes to delete a file from a directory while a program has it
opened. If the FILE were to remember the original name, that name would
then be wrong.

Why? It is still the name under which it was opened. Trying to
reopen it will probably fail. The things that get fouled include
anonymous temporary files, and i/o streams.
 
S

spibou

Richard said:
Naturally, since it's not a word. Try <http://www.acronymfinder.com/>
instead.

But dictionary.com knows the meaning of many acronyms
and if it doesn't it automatically forwards you to the page
of www.acronymfinder.com which does have the meaning.
Since in this case dictionary.com didn't do that I assumed
that acronymfinder.com didn't have the meaning either but
it actually does. So perhaps it's a bug with dictionary.com
 
C

CBFalconer

But dictionary.com knows the meaning of many acronyms
and if it doesn't it automatically forwards you to the page
of www.acronymfinder.com which does have the meaning.
Since in this case dictionary.com didn't do that I assumed
that acronymfinder.com didn't have the meaning either but
it actually does. So perhaps it's a bug with dictionary.com

It has to do withthe QOI of dictionary.com :)
 
E

Eric Sosman

CBFalconer said:
Why? It is still the name under which it was opened. Trying to
reopen it will probably fail. The things that get fouled include
anonymous temporary files, and i/o streams.

I guess it all gets back to what use the program plans
to make of the fname() string. If it's just for "decorative"
purposes (c.f. __FILE__ or argv[0]), it probably doesn't matter
much that the string might no longer be an accurate name for
the stream's file. But if the program makes "substantive" use
of the string -- passing it to rename(), say -- then accuracy
becomes an issue.

How much of an issue? "Bless you, it all depends!"
 
D

Dale Pennington

Bill Pursell said:
Dale Pennington wrote:

Out of curiousity, why the need? As others have pointed out, it's

I am responsible for a support library that other application writers in my
group use. The library provides a some file logging support. We recently
added a feature to support logs larger than the max filesize (by splitting
into multiple files with a specified naming convention). For the new
implementaion we changed to API from passing a FILE * to passing a custom
structure that contains the FILE * as well other information to support the
splitting operation
(including the file name).

Now for a specific test at a remote site with an older version of the code,
they want to retrofit the large files in without having to touch all the
application code. And while the original API provided an open function folks
were supposed to use, some did not (bad application programmers!). I was
hoping the get the file name on files opened with fopen vice my log API to
make the temporary implemention easier.

Thanks
Dale Pennington
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top