By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,638 Members | 1,983 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,638 IT Pros & Developers. It's quick & easy.

Getting the file name from a FILE *

P: n/a
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;
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #1
Share this Question
Share on Google+
185 Replies


P: n/a
On Jun 20, 6:11 pm, jacob navia <ja...@nospam.comwrote:
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...
Jun 27 '08 #2

P: n/a
jacob navia wrote:
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.
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;

Jun 27 '08 #3

P: n/a
In article <g3**********@aioe.org>, jacob navia <ja***@nospam.orgwrote:
>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?
--
"The Romans believed that every man had his Genius, and every
woman her Juno." -- Thomas Bulfinch
Jun 27 '08 #4

P: n/a
vi******@gmail.com wrote:
On Jun 20, 6:11 pm, jacob navia <ja...@nospam.comwrote:
>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?
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.
>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.
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...
>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...
Well this is standard C. The first line defines an opaque structure
called __FILE.
The second defines a pointer to that opaque structure.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #5

P: n/a
jacob navia schrieb:
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

--
"Wer etwas kritisiert muss es noch lange nicht selber besser können. Es
reicht zu wissen, daß andere es besser können und andere es auch
besser machen um einen Vergleich zu bringen." - Wolfgang Gerber
in de.sci.electronics <47***********************@news.freenet.de>
Jun 27 '08 #6

P: n/a
Joachim Schmitz wrote:
jacob navia wrote:
>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)?
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.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #7

P: n/a
Johannes Bauer wrote:
jacob navia schrieb:
>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*?
Yes!

Thanks for that tip.
>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.
Luckily we do not support the low level primitives (open/close/fdopen,
etc). Maybe in a future release...
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #8

P: n/a
On Jun 20, 7:00 pm, jacob navia <ja...@nospam.comwrote:
vipps...@gmail.com wrote:
On Jun 20, 6:11 pm, jacob navia <ja...@nospam.comwrote:
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?

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.
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.

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()).
>
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...

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.
Jun 27 '08 #9

P: n/a
On Jun 20, 7:08 pm, jacob navia <ja...@nospam.comwrote:
Johannes Bauer wrote:
jacob navia schrieb:
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*?

Yes!

Thanks for that tip.
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.

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
Jun 27 '08 #10

P: n/a
jacob navia wrote:
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 *);
I'd vote for fname().
What problems could arise with this function?
A few problems I can think of off-hand:

- Some streams might not be associated with named files.
The problem isn't insuperable -- you could return NULL
or "" or some such -- but it's a problem.

- Interaction with rename() and remove() could be tricky,
especially when a file has more than one name (e.g.,
"foo", "./foo", "/user/jnavia/projects/foo", ...).
Since the effect of rename() or remove() on a file with
open streams is implementation-defined, you're free to
define your way out of the problem by ignoring it, but
then one starts to ask whether the result of fname() is
useful. For decoration in messages, maybe, but ...

- Similar issues arise on systems that provide a "change
directory" operation, if the name is "relative" and the
directory changes between fopen() and fname().

- The returned type should probably be `const char*'.
Whether the argument should be const-qualified is a
trickier matter, since it would place constraints on
the implementation (e.g., no "lazy fill-in").
Why is not in the C API?
Sounds like a comp.std.c question. Speculation: The
committee was chartered to codify existing practice, and there
was insufficient existing practice for such a function.

--
Er*********@sun.com
Jun 27 '08 #11

P: n/a
jacob navia wrote:
Joachim Schmitz wrote:
>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.
[*] Well, it doesn't have *that* name. Because of what
Unix file systems call "hard links," a file can have many
aliases.

--
Er*********@sun.com
Jun 27 '08 #12

P: n/a
jacob navia wrote:
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.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jun 27 '08 #13

P: n/a
jacob navia <ja***@nospam.comwrites:
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
in <stdio.h>, even in non-conforming mode.
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]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #14

P: n/a
On Jun 20, 9:41 am, Eric Sosman <Eric.Sos...@sun.comwrote:
jacob navia wrote:
Joachim Schmitz wrote:
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.

--
Eric.Sos...@sun.com
Regards,
MingyanGuo
Jun 27 '08 #15

P: n/a
mingyanguo wrote:
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!

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #16

P: n/a
jacob navia wrote:
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>

Jun 27 '08 #17

P: n/a
jacob navia wrote:
mingyanguo wrote:
>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.
It's not rare at all, and the test is not reliable. One
scenario where this happens is in an editor that reads a file
into memory, massages it, and then wants to save the modified
version. Instead of overwriting the original file, which risks
catastrophic data loss if there's an ill-timed crash or I/O
failure or something, the editor may write to a temporary file,
then remove the original and rename the temporary:

data = loadData("file.dat");
massage(data);
saveData("file.tmp", data);
remove("file.dat"); // or rename("file.dat", "file.old")
rename("file.tmp", "file.dat");

Of course, if the programmer used the editor to make a
change near the end of a long file while leaving the first
ten thousand lines intact, comparing only "the first bytes"
is not sufficient.
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);
My own preference is for libraries that don't write such
messages, but instead pass the details of failures and such
upwards to their callers. The callers can then choose whether
to write to stderr -- or to open a dialog box, or send a text
message to somebody's pager, or make an entry in the system
logging service, or ...
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!
Hence, useful only for "decorative" purposes. That's fine,
but it's not a feature that appears to add a lot of value.
(Which is good news, in a way, because it lets you get away
with a "close enough for jazz" effort. This is one of those
situations where doing a ninety-percent job is trivial but
doing a hundred-percent job is damn' near impossible.)

--
Er*********@sun.com
Jun 27 '08 #18

P: n/a
vi******@gmail.com wrote:
>
On Jun 20, 6:11 pm, jacob navia <ja...@nospam.comwrote:
[... getting filename from 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...
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:Th*************@gmail.com>
Jun 27 '08 #19

P: n/a
jacob navia wrote:
>
vi******@gmail.com wrote:
On Jun 20, 6:11 pm, jacob navia <ja...@nospam.comwrote:
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?

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:Th*************@gmail.com>

Jun 27 '08 #20

P: n/a
Keith Thompson wrote, On 20/06/08 18:29:
jacob navia <ja***@nospam.comwrites:
>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
in <stdio.h>, even in non-conforming mode.
It would certainly break lots of SW I have access to. I would vote for
__fname.
>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.
<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.
--
Flash Gordon
Jun 27 '08 #21

P: n/a
jacob navia wrote:
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?
_fname

What problems could arise with this function?
Non-portable code.

--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>
Jun 27 '08 #22

P: n/a
Tor Rustad wrote:
jacob navia wrote:
>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?

_fname

Yes, it is better with the underscore
>What problems could arise with this function?

Non-portable code.
That is not a problem with the function.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #23

P: n/a
Walter Roberson wrote:
In article <g3**********@aioe.org>, jacob navia <ja***@nospam.orgwrote:
>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?
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!
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #24

P: n/a
On Fri, 20 Jun 2008 23:03:33 +0200, jacob navia wrote:
Walter Roberson wrote:
>In article <g3**********@aioe.org>, jacob navia <ja***@nospam.orgwrote:
>>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?

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!
This sounds like a terrible idea to me. Consider a program that opens tens
of thousands of files simultaneously, all with long filenames, say 100 or
200 bytes each. You could easily be wasting 1MB or more just storing
copies of all the filenames in your standard library.

Jun 27 '08 #25

P: n/a
In article <pa****************************@spam.com>,
Chris Peters <no@spam.comwrote:
>Consider a program that opens tens
of thousands of files simultaneously, all with long filenames, say 100 or
200 bytes each. You could easily be wasting 1MB or more just storing
copies of all the filenames in your standard library.
As Jacob is writing the implementation of fopen(), he could choose to
limit the number of simultaneously open files, possibly even according
to whether he has "room" to store the new filename (though he
wouldn't want to get into compacting out holes in a static name
array, as that could end up moving filenames around after the name
pointer had already been made available to to program.)

On POSIX systems, the minimum maximum number of simultaneous open
files is just 16. 200 or 255 are common (traditionally the file
descriptor number was a single byte.)

Checking around a bit, I see that the default hard limit in NT
is 10000 files, and that apparently for some people that's a problem.
Odd. It's alterable, apparently,
http://support.microsoft.com/kb/326591/en-us
There's a mention of NetDDE (Dynamic Data Exchange) as being an
example of when it could be a problem. On the other hand,
NetDDE was removed from Windows Vista, it appears
http://en.wikipedia.org/wiki/Dynamic_Data_Exchange

--
"Let me live in my house by the side of the road --
It's here the race of men go by.
They are good, they are bad, they are weak, they are strong
Wise, foolish -- so am I;" -- Sam Walter Foss
Jun 27 '08 #26

P: n/a
Chris Peters wrote:
On Fri, 20 Jun 2008 23:03:33 +0200, jacob navia wrote:
>What You Get Is What You Opened!

This sounds like a terrible idea to me. Consider a program that opens tens
of thousands of files simultaneously, all with long filenames, say 100 or
200 bytes each. You could easily be wasting 1MB or more just storing
copies of all the filenames in your standard library.
If you open 10 thousand files with each a name of
256 chars, you get 256*10000-->2 560 000 bytes,
2MB.

Nothing for a machine that can open 10 000 files simultaneously.

Those machines have now routinely 1GB installed.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #27

P: n/a
On Jun 20, 7:14*pm, jacob navia <ja...@nospam.comwrote:
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.
That is pathetic. The customary way of updating files in MacOS X is to
write a copy of the modified file, then using a (non-standard C) call
to exchange the original and the modified file, and finally deleting
the original. If application B does that while your application A does
its clever thing, data loss is inevitable.
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.
You should really get used to looking a bit further than Windows.

What you are suggesting is in the end a function that returns the name
that was used to open a file, not the name of the file. That is
trivial to implement for anyone who wants it, and not very useful. If
you can implement a function that will either return the _correct_
name of a file or determine that there is no name, go ahead and do it.
Jun 27 '08 #28

P: n/a
jacob navia <ja***@nospam.comwrites:
[...]
The file name is the first parameter of the
fopen call. No matter what that is. That will
be returned.

Easy isn't it?
[...]

Not really.

What if the file wasn't opened via fopen()?

Among standard functions, tmpfile() and freopen() probably aren't much
of a problem, but you at least need to think about them.

There might be more serious problems if you support non-standard
functions that return FILE* results (popen(), for example).

(In your initial description, you mentioned "lower case"; re-reading
it, I think you were referring to the name "fopen", not to the result
it returns.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #29

P: n/a
In article <g3**********@aioe.org>, jacob navia <ja***@nospam.orgwrote:
>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.
But why would you want to do this at all? If you already have the
file open, why open it again? Just what is the problem you are trying
to solve?

The most obvious use for having the file name is to give better error
messages (as in your example), and for that none of these issues are
important. So long as users understand the limited uses of the file
name, it seems like a handy addition.

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #30

P: n/a
In article <e4**********************************@a70g2000hsh. googlegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>You should really get used to looking a bit further than Windows.
If you're selling a compiler that only works with Windows, it doesn't
matter that your extensions rely on Windoziness.
>What you are suggesting is in the end a function that returns the name
that was used to open a file, not the name of the file. That is
trivial to implement for anyone who wants it, and not very useful.
It's very useful for producing better error messages, and can't be
reasonably implemented by the user without changing existing
interfaces.

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #31

P: n/a
In article <pa****************************@spam.com>,
Chris Peters <no@spam.comwrote:
>This sounds like a terrible idea to me. Consider a program that opens tens
of thousands of files simultaneously, all with long filenames, say 100 or
200 bytes each. You could easily be wasting 1MB or more just storing
copies of all the filenames in your standard library.
And each of them quite likely has a buffer associated with it. By
comparison the filename is unlikely to be significant, and of course
most filenames aren't anything like 200 bytes.

A more important limitation, mentioned in various forms by other
posters, is that many files just aren't opened by fopen() in the
current process. They're inherited, or are pipes or sockets or
who-knows-what. But perhaps that's rarer in Windows, and in any case
it's handy to have the filename for those cases where it is possible.

-- Richard

--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #32

P: n/a
Richard Tobin wrote:
In article <e4**********************************@a70g2000hsh. googlegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>You should really get used to looking a bit further than Windows.

If you're selling a compiler that only works with Windows, it doesn't
matter that your extensions rely on Windoziness.
Until you try to port either the compiler or the code that builds with
it. Sounds like M$ standard practice :)

--
Ian Collins.
Jun 27 '08 #33

P: n/a
jacob navia wrote:
>
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?
Many large problems on Linux/Unix. A file may be accessed via a
name, but once open it is nameless, and may well be identical to a
file opened with another program under another name, including
using identical storage. This is simply not a possible function.
If you want to know what name you used to open it, all you have to
do is remember it.

Just because things work on primitive operating systems, such as
Winders, doesn't mean they can work everywhere.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #34

P: n/a
CBFalconer <cb********@yahoo.comwrites:
jacob navia wrote:
>>
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?

Many large problems on Linux/Unix. A file may be accessed via a
name, but once open it is nameless, and may well be identical to a
file opened with another program under another name, including
using identical storage. This is simply not a possible function.
If you want to know what name you used to open it, all you have to
do is remember it.

Just because things work on primitive operating systems, such as
Winders, doesn't mean they can work everywhere.
There is no such OS as Winders as far as I know. Please refrain from
using silly slang in a technical news group - as you frequently remind
others.

Jun 27 '08 #35

P: n/a
"christian.bau" wrote:
>
.... snip ...
>
What you are suggesting is in the end a function that returns the
name that was used to open a file, not the name of the file. That
is trivial to implement for anyone who wants it, and not very
useful. If you can implement a function that will either return
the _correct_ name of a file or determine that there is no name,
go ahead and do it.
That last is impossible under Unix/Linux. A file, and its storage,
is specified separately from directory entries. Any directory
entry may be linked to that file. It can then be used to open the
file, read from it, write to it, etc. (depending on permissions).
Those are known as links. When the last link is deleted that file
is no longer accessible, and the system deletes it. Users don't
delete files, they delete links.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #36

P: n/a
jacob navia wrote:
Walter Roberson wrote:
.... snip ...
>
>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
Nope. While the file was open, another process deleted the same
file and opened a new file under the same name. Now any fopens
will access the new file. However, the old file is still open,
usable, and nameless. Under Linux/Unix/Posix.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #37

P: n/a

"jacob navia" <ja***@nospam.comschreef in bericht
news:g3**********@aioe.org...
What problems could arise with this function? Why is not in the C API?
I wouldn't put this in libc, it's something people can add themselves easily
when they need it.

But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into? And will you provide a wide char version too for
consistency?

Jun 27 '08 #38

P: n/a
In article <cc***************************@cache2.tilbu1.nb.ho me.nl>,
Serve Lau <ni***@qinqin.comwrote:
>But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into?
How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #39

P: n/a

"Richard Tobin" <ri*****@cogsci.ed.ac.ukschreef in bericht
news:g3***********@pc-news.cogsci.ed.ac.uk...
In article <cc***************************@cache2.tilbu1.nb.ho me.nl>,
Serve Lau <ni***@qinqin.comwrote:
>>But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into?

How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?
That will require more knowledge of internal workings of standard C
functions which is IMO never a good thing.
Jun 27 '08 #40

P: n/a
jacob navia skrev:
Tor Rustad wrote:
>jacob navia wrote:
[...]
>>Questions:

What would be the best name for this function?

_fname


Yes, it is better with the underscore
It avoid polluting the name space.

I have often used 'fname' as an identifier in my own projects, and
wouldn't take it lightly if the compiler I was using, didn't accept
strictly conforming code because of such a thing.

>>What problems could arise with this function?

Non-portable code.

That is not a problem with the function.
From the point of a user, unless we talk about throw away programs,
it's a major problem if code can only be compiled with one compiler. In
lcc-win case, who knows how long that particular compiler will be supported?
When I write non-portable code, it does something useful. Typically, the
problem at hand, can't be solved via portable methods. I suspect you are
wasting your time, by implementing this feature.

--
Tor <bw****@wvtqvm.vw | tr i-za-h a-z>
Jun 27 '08 #41

P: n/a
In article <9c**************************@cache2.tilbu1.nb.hom e.nl>,
>>>But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into?
>How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?
>That will require more knowledge of internal workings of standard C
functions which is IMO never a good thing.
I'm baffled. Aren't we talking about Jacob's implementation?
He's the implementor of the functions, he's supposed to know
about their internal workings.

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #42

P: n/a
Serve Lau wrote:
>
But anyway, how will you store the strings? You cant store pointers so
you have to go for string copying. But how large will you make the
arrays you will copy the names into? And will you provide a wide char
version too for consistency?
I *can* store pointers.

fopen:

File->FileName = strdup(fname);

fclose:
free(File->FileName);

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #43

P: n/a
Serve Lau wrote:
"Richard Tobin" <ri*****@cogsci.ed.ac.ukschreef in bericht
>How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?

That will require more knowledge of internal workings of standard C
functions which is IMO never a good thing.
What knowledge of internal workings am I required to know for writing:
#include <stdlib.h>
char *s = NULL;
void foo(char *bar) {if (s = malloc(strlen(bar)+1)) strcpy(s, bar);}

Besides, the implementor of fopen() really should have knowledge of
the internal working of standard C functions like fgetc, fwrite, etc.

Ralf
Jun 27 '08 #44

P: n/a
In article <g3***********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
>In article <cc***************************@cache2.tilbu1.nb.ho me.nl>,
Serve Lau <ni***@qinqin.comwrote:
>>But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into?
>How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?
I do not have my C89 hardcopy here to check against. I know that there
are various routines that are marked with wording similar to
"The implementation shall behave as if no library routine
calls <name>". I do not recall if malloc() is one of those routines ?
--
"They called it golf because all the other four letter words
were taken." -- Walter Hagen
Jun 27 '08 #45

P: n/a
Walter Roberson wrote:
In article <g3***********@pc-news.cogsci.ed.ac.uk>,
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
>In article <cc***************************@cache2.tilbu1.nb.ho me.nl>,
Serve Lau <ni***@qinqin.comwrote:
>>But anyway, how will you store the strings? You cant store pointers so you
have to go for string copying. But how large will you make the arrays you
will copy the names into?
>How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?

I do not have my C89 hardcopy here to check against. I know that there
are various routines that are marked with wording similar to
"The implementation shall behave as if no library routine
calls <name>". I do not recall if malloc() is one of those routines ?
No, it is not. Lots of fopen() implementations, for
example, obtain I/O buffers from malloc().

--
Eric Sosman
es*****@ieee-dot-org.invalid
Jun 27 '08 #46

P: n/a

"Richard Tobin" <ri*****@cogsci.ed.ac.ukschreef in bericht
news:g3***********@pc-news.cogsci.ed.ac.uk...
In article <9c**************************@cache2.tilbu1.nb.hom e.nl>,
>>>>But anyway, how will you store the strings? You cant store pointers so
you
have to go for string copying. But how large will you make the arrays
you
will copy the names into?
>>How about the right length? Are you suggesting that there's some
reason why fopen() shouldn't malloc() the space?
>>That will require more knowledge of internal workings of standard C
functions which is IMO never a good thing.

I'm baffled. Aren't we talking about Jacob's implementation?
He's the implementor of the functions, he's supposed to know
about their internal workings.
I meant the people *using* fopen. What if malloc fails? Should fopen return
NULL suddenly while the file couldve been opened?
Jun 27 '08 #47

P: n/a

"jacob navia" <ja***@nospam.comschreef in bericht
news:g3**********@aioe.org...
Serve Lau wrote:
>>
But anyway, how will you store the strings? You cant store pointers so
you have to go for string copying. But how large will you make the arrays
you will copy the names into? And will you provide a wide char version
too for consistency?

I *can* store pointers.

fopen:

File->FileName = strdup(fname);

fclose:
free(File->FileName);
Yes but it can fail. Will fopen return NULL on failure of strdup or return a
valid FILE pointer. When the buffer fails to be allocated in fopen this is a
critical error and fopen should return NULL but not being able to allocate
the filename is not crititical and if you return NULL one cant distingish
between allocation failure and "non named files" anymore. I really think you
should keep this out the library and let clients deal with this who have
more context in their own programs anyway.
>
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #48

P: n/a
Walter Roberson wrote:
The implementation shall behave as if no library routine
calls
From n1256:

7.11.1.1(5)
The implementation shall behave as if no library function calls the
setlocale function.

7.11.2.1(7)
The implementation shall behave as if no library function calls the
localeconv function.

7.14.1.1(7)
The implementation shall behave as if no library function calls the
signal function.

7.19.4.4(4)
The implementation shall behave as if no library function calls the
tmpnam function.

7.20.2.1(3)
The implementation shall behave as if no library function calls the rand
function.

7.20.2.2(3)
The implementation shall behave as if no library function calls the
srand function.

7.20.4.5(3)
The implementation shall behave as if no library function calls the
getenv function.

7.20.7.1(3)
The implementation shall behave as if no library function calls the
mblen function.

7.20.7.2(3)
The implementation shall behave as if no library function calls the
mbtowc function.

7.20.7.3(3)
The implementation shall behave as if no library function calls the
wctomb function.

7.21.5.8(6)
The implementation shall behave as if no library function calls the
strtok function.

7.21.6.2(3)
The implementation shall behave as if no library function calls the
strerror function.

7.24.6.3(1)
Restartable multibyte/wide character conversion functions
[ ... ]
The implementation behaves as if no library function calls these
functions with a null pointer for ps.

7.24.6.4(1)
Restartable multibyte/wide string conversion functions.
[ ... ]
The implementation behaves as if no library function calls these
functions with a null pointer for ps.

Jun 27 '08 #49

P: n/a
In article <19***************************@cache5.tilbu1.nb.ho me.nl>,
Serve Lau <ni***@qinqin.comwrote:
>I meant the people *using* fopen. What if malloc fails? Should fopen return
NULL suddenly while the file couldve been opened?
That can happen anyway, if it can't allocate the FILE struct or the
buffer. A few extra bytes for an open file is neither here nor there
on typical systems.

If you were talking about an embedded system it might be an issue, but
so would be the whole of stdio.

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #50

185 Replies

This discussion thread is closed

Replies have been disabled for this discussion.