Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
Of course, this effect isn't limited to `Assign'. The issue applies to any way of storing file names, provided that changing directories is possible at all.
A solution would be to store the expanded file name (i.e., turn it into an absolute path whenever possible -- I currently don't know any case where it wouldn't be possible).
Of course, this wouldn't be strictly BP compatible, but I wonder if this is a "good" or "bad" incompatibility. (Of course, the difference would be subtler and more confusing if there actually was a file `test.dat' in the new directory.) Also, clearly a new `Assign' statement after the change of directory would refer to the new directory, as would be expected.
How do other compilers behave? What would be the expected behaviour of code like above if it actually occurs in practice?
Frank
On Fri, Apr 02, 2004 at 12:59:30PM +0200, Frank Heckenbach wrote:
Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
[...]
How do other compilers behave? What would be the expected behaviour of code like above if it actually occurs in practice?
Frank
IMHO this is quite natural. There's no reason to close the file if I want its "identity" to be preserved.
Emil
Emil Jerabek wrote:
On Fri, Apr 02, 2004 at 12:59:30PM +0200, Frank Heckenbach wrote:
Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
[...]
How do other compilers behave? What would be the expected behaviour of code like above if it actually occurs in practice?
Frank
IMHO this is quite natural. There's no reason to close the file if I want its "identity" to be preserved.
I'm not sure. I'd rather consider `Assign' to be "identity giving" in this context. BTW, without closing it works under GPC and still fails under BP.
Frank
On Fri, 2 Apr 2004, Frank Heckenbach wrote:
Emil Jerabek wrote:
On Fri, Apr 02, 2004 at 12:59:30PM +0200, Frank Heckenbach wrote:
Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
Actually, under gpc it works exactly as I would expect it to work. (To try it under BP I would have to setup the old computer). I can have two different files having the same name as long as they are in different directories.
As a test, changed 42 to 123 and compiled, ran. Got an error message as expected. Next, "mv test.dat .. " Then changed 123 back to 42, comiled, ran. Got 123 and no error message.
Russ
On Fri, 2 Apr 2004, Frank Heckenbach wrote:
Emil Jerabek wrote:
On Fri, Apr 02, 2004 at 12:59:30PM +0200, Frank Heckenbach wrote:
Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
[...]
How do other compilers behave? What would be the expected behaviour of code like above if it actually occurs in practice?
Frank
IMHO this is quite natural. There's no reason to close the file if I want its "identity" to be preserved.
I'm not sure. I'd rather consider `Assign' to be "identity giving" in this context. BTW, without closing it works under GPC and still fails under BP.
Frank
Would be interesting to know if there are any standards on this (Is Scott Moore paying any attention?)... my own view would be that once a file is open, it's open and you ought to be able access it even if you change directories and even if someone else changes the name of the file (which is one of the reasons why OS' generally only allow one process write access to a file at a time). File name assignments, on the other hand, should be relative to the current directory; thus, in the example above, the program should try to open "test.dat" in the current directory both times (2 different files, unless they're linked).
-------------------------| John L. Ries | Salford Systems | Phone: (619)543-8880 x25 | (760)765-4738 | Cell: (760)445-6122 | -------------------------
John L. Ries wrote:
Would be interesting to know if there are any standards on this
Extended Pascal has bindings which have the same issues. But AFAICS the description of the external relationship is very vague, and since "The binding shall be implementationÂÂdefined.", I suppose almost any behaviour would be allowed.
(Is Scott Moore paying any attention?)... my own view would be that once a file is open, it's open and you ought to be able access it even if you change directories and even if someone else changes the name of the file
This is true in any case as long as the file remains open. The question is what happens if the file is "reopened" (e.g., `Rewrite', then `Reset'). How do we interpret this? Is it still (meant to be) the same file, opened in a different mode, or do we open another file (which may happen to be the same file as before if names and directories weren't changed). According to Waldek's comments, the problems in the first case seem to be bigger, though.
(which is one of the reasons why OS' generally only allow one process write access to a file at a time).
I don't know which OS's you use, but mine generally allow multiple write access, unless expliclty locked. (Quite useful for shared logfiles, e.g.)
Frank
Frank Heckenbach wrote:
Hi,
there's a strange case when using relative file names and changing the directory. (Incidentally I was made aware of this by a bugfix in the ncurses library (C code) some while ago ... ;-) Consider this program:
program Foo;
var i: Integer; f: Text;
begin Assign (f, 'test.dat'); Rewrite (f); WriteLn (f, 42); Close (f); ChDir ('..'); Reset (f); ReadLn (f, i); WriteLn (i) end.
It fails under both GPC and BP because `Reset' tries to open a file `test.dat' in a different directory than it was created.
Of course, this effect isn't limited to `Assign'. The issue applies to any way of storing file names, provided that changing directories is possible at all.
A solution would be to store the expanded file name (i.e., turn it into an absolute path whenever possible -- I currently don't know any case where it wouldn't be possible).
Fails if current directory is deleted.
Of course, this wouldn't be strictly BP compatible, but I wonder if this is a "good" or "bad" incompatibility. (Of course, the difference would be subtler and more confusing if there actually was a file `test.dat' in the new directory.) Also, clearly a new `Assign' statement after the change of directory would refer to the new directory, as would be expected.
I expect to be able to move (rename) a directory in which a programm is running without disruption, provided the program uses relatiove paths in subdirectories. Change to absolute paths would break such assumption. I personaly always did `Assign' just before `Reset' or `Rewrite' and expect most programs to do the same. IMHO opening a file should be an atomic operation and splitting opening into `Assign' and `Reset' is prone to races and unexpected side effects. Note that current semantic does give a warranty: file with simple name will be open in current directory. Proposed change introduces a race: file will be open in the directory which has the name current direcory had at `Assign' time. Even if program stays in the same directory the name may change.
In short: I think that only tiny fraction of programs will "benefit" and that slightly more programs will be broken. For me clearily benefits do not justify implementing the change.
Waldek Hebisch wrote:
A solution would be to store the expanded file name (i.e., turn it into an absolute path whenever possible -- I currently don't know any case where it wouldn't be possible).
Fails if current directory is deleted.
Right. But then opening the file again will fail anyway ...
Of course, this wouldn't be strictly BP compatible, but I wonder if this is a "good" or "bad" incompatibility. (Of course, the difference would be subtler and more confusing if there actually was a file `test.dat' in the new directory.) Also, clearly a new `Assign' statement after the change of directory would refer to the new directory, as would be expected.
I expect to be able to move (rename) a directory in which a programm is running without disruption, provided the program uses relatiove paths in subdirectories. Change to absolute paths would break such assumption.
I see, this is a valid point.
I personaly always did `Assign' just before `Reset' or `Rewrite' and expect most programs to do the same. IMHO opening a file should be an atomic operation and splitting opening into `Assign' and `Reset' is prone to races and unexpected side effects.
We could discuss this, but since both EP (bindings) and BP (Assign) work this way, we don't really have a choice here ...
Note that current semantic does give a warranty: file with simple name will be open in current directory. Proposed change introduces a race: file will be open in the directory which has the name current direcory had at `Assign' time. Even if program stays in the same directory the name may change.
In short: I think that only tiny fraction of programs will "benefit" and that slightly more programs will be broken. For me clearily benefits do not justify implementing the change.
I tend to agree. Still, there's some strange behaviour:
program Foo;
var f: file of Integer;
begin Assign (f, 'test.dat'); Reset (f); ChDir ('..'); Rewrite (f); end.
Here `test.dat' msut exist when the program starts. If it is readable and writable, the program will use it both times. If it's readonly, the program will create a new file (because it's not writable), and this will be in the new directory. We could think about always reopening the file, but especially for `SeekRead' etc. (EP) this would be rather inefficient I think.
So perhaps we should just accept it (especially since neither EP nor BP seem to really define this case either). "Don't do that then."
Frank