Getting the file name from a FILE *

J

jacob navia

Hi
We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.

Questions:

What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

// clear name but maybe too long?
char *FileNameFromFileP(FILE *);

What problems could arise with this function? Why is not in the C API?

We are considering extending our file functions to handle
file attributes that many file systems support. We will have two
pointers that point to extended attributes and a "user" pointer,
i.e. a pointer that would be set by the user and would carry user
defined data that we would not touch. An accessor/setter function
would allow the user to set/retrieve data.

Note that the FILE structure is now a completely opaque structure.
No definition for FILE will be available to the user but

struct __FILE;
typedef struct __FILE FILE;
 
V

vippstar

Hi
We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.
What should it return for tempfile(), stdin, stdout, stderr?
Questions:

What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

// clear name but maybe too long?
char *FileNameFromFileP(FILE *);

What problems could arise with this function? Why is not in the C API?
Because FILE needs not to be a struct.
Also, why not just write it as a macro in all caps? All you do is
return an element from the struct anyway...
We are considering extending our file functions to handle
file attributes that many file systems support. We will have two
pointers that point to extended attributes and a "user" pointer,
i.e. a pointer that would be set by the user and would carry user
defined data that we would not touch. An accessor/setter function
would allow the user to set/retrieve data.

Note that the FILE structure is now a completely opaque structure.
No definition for FILE will be available to the user but

struct __FILE;
typedef struct __FILE FILE;
I don't understand these last two lines...
 
J

Joachim Schmitz

jacob said:
Hi
We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.

Questions:

What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

// clear name but maybe too long?
char *FileNameFromFileP(FILE *);

What problems could arise with this function? Why is not in the C API?
What happens if the file gets deleted (remove()/unlink()), while it is still
open (in POSIX that is possible, not sure what the C Standard nor Windowds
says about this)?
In that case the filename would have disappeared, no longer exist.
 
W

Walter Roberson

We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.

What is the "file name" of a socket or pipe? Of a file created
by tmpnam() ? Of stdin? If all the calling program hands you is
the open file, then -which- of the several possible names for it
are you going to find for the file, in a system which has true symbolic
links? In a system which has Alternate Data Streams (ADS) that
can be programs that have effects similar to symbolic links or
to loop-back mounts?
 
J

jacob navia

What should it return for tempfile(), stdin, stdout, stderr?

For tempfile() should return... the name of the temporary file of course
For stdin it will return an invalid file name (either NULL or
"....stdin...." or similar.
For stdout/stderr the same.
Because FILE needs not to be a struct.

Yes, but why can't the C library return a file name from
the FILE *?

This has noting to do with the actual layout of the FILE

Also, why not just write it as a macro in all caps? All you do is
return an element from the struct anyway...

I don't understand these last two lines...

Well this is standard C. The first line defines an opaque structure
called __FILE.
The second defines a pointer to that opaque structure.
 
J

Johannes Bauer

jacob said:
What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

Shouldn't you return a const char*?
What problems could arise with this function? Why is not in the C API?

What are you doing with open -> fdopen FILE*s? All you have is the file
descriptor here, no way to get a file name.

Regards,
Johannes
 
J

jacob navia

Joachim said:
What happens if the file gets deleted (remove()/unlink()), while it is still
open (in POSIX that is possible, not sure what the C Standard nor Windowds
says about this)?

If the file is still open and you can delete the file, the name of
the file doesn't change of course. It is still whatever it was.
And if you can still fwrite to an inexistent file, then
what happens with the name is not as important as what
happens with the data you write into... yes into what?

In that case the filename would have disappeared, no longer exist.

The file name will be returned by fopen if the file
is not closed. If that file exists, or not, that is not
our problem. If you did a

format c:

and the whole drive doesn't exist, this is NOT our problem.
 
J

jacob navia

Johannes said:
Shouldn't you return a const char*?

Yes!

Thanks for that tip.
What are you doing with open -> fdopen FILE*s? All you have is the file
descriptor here, no way to get a file name.

Luckily we do not support the low level primitives (open/close/fdopen,
etc). Maybe in a future release...
 
V

vippstar

For tempfile() should return... the name of the temporary file of course
For stdin it will return an invalid file name (either NULL or
"....stdin...." or similar.
For stdout/stderr the same.


Yes, but why can't the C library return a file name from
the FILE *?

This has noting to do with the actual layout of the FILE
It's actually useless. If the programmer cares, he can write his own
struct (and functions that modify it), for example
struct myfile { FILE *fp; const char *filename; }
I remember another thread where someone asked why there isn't an
isodigit (similar to isxdigit, for octal numbers)
Presumably for the same reason: they either haven't though of it, or
because it's easy to implement.
Same say for memmem() (like strstr()).
Well this is standard C. The first line defines an opaque structure
called __FILE.
The second defines a pointer to that opaque structure.
Ah yeah, sorry for that, it confused me so much, but now it seems
quite clear that what it does is ok. (It defines an alias, not a
pointer though)
Why do that instead of simply struct FILE?
Mr Joahim Schmitz made a valid point: what do you do when remove() is
called?

Also, *WHY* do you want to add that? It doesn't seem particularly
useful to me.
 
V

vippstar

Yes!

Thanks for that tip.



Luckily we do not support the low level primitives (open/close/fdopen,
etc). Maybe in a future release...

I don't see how what Mr Schmitz says is a problem.
You don't have to implement these, they are POSIX, and windows has
them as well. It's known that mixing read/write/etc calls with FILE*
can result in weird behavior, and that is not because of the way *you*
implemented FILE * and related functions
 
D

Daniel Pitts

jacob said:
Hi
We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.

Questions:

What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

// clear name but maybe too long?
char *FileNameFromFileP(FILE *);

What problems could arise with this function? Why is not in the C API?

We are considering extending our file functions to handle
file attributes that many file systems support. We will have two
pointers that point to extended attributes and a "user" pointer,
i.e. a pointer that would be set by the user and would carry user
defined data that we would not touch. An accessor/setter function
would allow the user to set/retrieve data.

Note that the FILE structure is now a completely opaque structure.
No definition for FILE will be available to the user but

struct __FILE;
typedef struct __FILE FILE;
Why are you saving the filename? That seems like a bad idea, unless it
is necessary to implement the system code. Keep the FILE * to its core
purpose. Follow the KISS principal.
 
K

Keith Thompson

jacob navia said:
We are rewriting the libc for the 64 bit version of lcc-win
and we have added a new field in the FILE structure:
char *FileName;
fopen() will save the file name and an accessor function
will return the file name given a FILE *.

Questions:

What would be the best name for this function?
char *fname(FILE *); // lower case, short, similar to other
// file functions

// clear name but maybe too long?
char *FileNameFromFileP(FILE *);

I mildly prefer "fname". I strongly suggest that it *not* be declared
What problems could arise with this function?

It assumes that each stream is associated with exactly one file name.
Depending on the system, some streams are not associated with any
named file, and some many have multiple equally valid names.

There are a number of decisions you'd have to make *and document*
about the form of the name. For Windows, you've already specified
lower case, which isn't necessarily ideal. Other possibilities are
the name used to open it, and the name as stored in the directory
(NTFS remembers case distinctions in file names, but doesn't enforce
them).

Does the Windows API already provide something like this? I have no
idea whether it does or not; if it does, the existing interface might
provide some guidance, or even make your function unnecessary.

You should think about when and whether the name is going to be
useful. If you grab the name of a file and then close it, can you
re-open it with the same name?
Why is not in the C API?

I don't know. Probably lack of existing practice and limited utility.
It's usually easy enough to remember the name when you open the file.

[snip]
 
M

mingyanguo

jacob said:
Joachim said:
jacob navia wrote:
[...]
fopen() will save the file name and an accessor function
will return the file name given a FILE *.
[...]
What problems could arise with this function? Why is not in the C API?
What happens if the file gets deleted (remove()/unlink()), while it is
still open (in POSIX that is possible, not sure what the C Standard
nor Windowds says about this)?
If the file is still open and you can delete the file, the name of
the file doesn't change of course. It is still whatever it was.

This is not the case on Unix-derived systems. If the
file is deleted while open, it has *no* name[*]. Furthermore,
the former name can be used to create a new file that need
not have anything to do with the nameless file.

This is the point. A process opens file 'A', gets a FILE for it and
remembers its name 'A'. Then another process unlinks file 'A' and
reuses the name 'A' to create another file. Now if the previous
process tries to refer a file via the file name 'A', it will get the
new file, and worse, it is difficult for the process to know if the
file named 'A' is the one it opened or a new file created by others.
So, remembering the file name for a FILE rarely makes sense.
[*] Well, it doesn't have *that* name. Because of what
Unix file systems call "hard links," a file can have many
aliases.

Regards,
MingyanGuo
 
J

jacob navia

mingyanguo said:
This is the point. A process opens file 'A', gets a FILE for it and
remembers its name 'A'. Then another process unlinks file 'A' and
reuses the name 'A' to create another file. Now if the previous
process tries to refer a file via the file name 'A', it will get the
new file, and worse, it is difficult for the process to know if the
file named 'A' is the one it opened or a new file created by others.

1) It is not difficult at all to see if the name still matches
the contents of the file. Open the file with that name
and compare the first bytes... If the data matches with the
data in the still opened original file they are the same.
That would make you immune against this quite rare problem.

2) Under windows it is not possible to erase a file that is
already open by another process, as far as I know. If
under Unix, you have to take care that when you get the
file name you should not assume that the file is still there.
All this is not the problem of fopen.
So, remembering the file name for a FILE rarely makes sense.

It makes sense in most applications, specially when you write
a library and you receive a FILE pointer, and you want to
write a more comprehensible error message than:
fprintf(stderr,"Can't write to file %p\n",file);

There will be no guarantee that the file name is unique, that
the file name corresponds to a still existing file, etc. It will be
just the argument you passed to fopen!
 
S

santosh

jacob said:
mingyanguo wrote: [ ... ]
So, remembering the file name for a FILE rarely makes sense.

It makes sense in most applications, specially when you write
a library and you receive a FILE pointer, and you want to
write a more comprehensible error message than:
fprintf(stderr,"Can't write to file %p\n",file);

You can have your library function take an additional char * parameter
specifying the file name, which the caller will surely be knowing.

<snip>
 
F

Flash Gordon

Keith Thompson wrote, On 20/06/08 18:29:
I mildly prefer "fname". I strongly suggest that it *not* be declared
in <stdio.h>, even in non-conforming mode.

It would certainly break lots of SW I have access to. I would vote for
__fname.
It assumes that each stream is associated with exactly one file name.
Depending on the system, some streams are not associated with any
named file, and some many have multiple equally valid names.

<snip>

You can play the game with DOS to a degree. If you could the path as
part of the name you can definitely do this with Windows on NTFS.

Or the name you opened it with might not be the real name just a pointer
to it.
 
K

Kenneth Brody

On Jun 20, 6:11 pm, jacob navia <[email protected]> wrote:
[... getting filename from FILE* ...
Because FILE needs not to be a struct.
Also, why not just write it as a macro in all caps? All you do is
return an element from the struct anyway...

And what would FunctionToGetFilenameFromFilePointer(stdout) return?

(I suppose "this function returns NULL if the filename cannot be
determined" may suffice here.)

BTW, we "solved" this for our own library by putting wrappers around
fopen/fclose (as well as open/close) to keep track of filenames for
files which we open. This allows, for example, error messages to
include 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]>
 
K

Kenneth Brody

jacob said:
For tempfile() should return... the name of the temporary file of course

What if the file doesn't have a name? Some implementations of
tmpfile() work by creating and opening a file, and then deleting
the file while still open. The filename used to create the file
is no longer valid, and creating a file with that same name will
create a different file.
For stdin it will return an invalid file name (either NULL or
"....stdin...." or similar.

NULL would be better IMO, as it's easier to check for "failure",
and calling fopen("...stdin...","r") won't do what you want.

[...]

--
+-------------------------+--------------------+-----------------------+
| 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]>
 
J

jacob navia

Walter said:
What is the "file name" of a socket or pipe? Of a file created
by tmpnam() ? Of stdin? If all the calling program hands you is
the open file, then -which- of the several possible names for it
are you going to find for the file, in a system which has true symbolic
links? In a system which has Alternate Data Streams (ADS) that
can be programs that have effects similar to symbolic links or
to loop-back mounts?

The file name is the first parameter of the
fopen call. No matter what that is. That will
be returned.

Easy isn't it?

fopen remembers the file name, and that is what you get

WYGIWYO

What You Get Is What You Opened!
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top