Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2013-08

ExpandFileName failure on long filenames on Linux

17 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi,

Before reporting this as a bug, can somebody confirm?

program efn;
uses sysutils;
begin
  writeln(expandfilename(paramstr(1)));
end.
If I cd to a directory with a very long name (>255 chars) and then
exeucte the following:
$ ~/LazarusProjecten/bugs/findfirst/efn .

It prints out only the first 255 characters of the current directory. (This issue poped up whilst investigating
http://bugs.freepascal.org/view.php?id=24885)

Bart

Michael Van Canneyt
to Bart
Bart wrote 19 lines
Hi, Before reporting this as a bug, can somebody confirm? program efn; uses sysutils; begin writeln(expandfilename(paramstr(1))); end. If I cd to a directory with a very long name (>255 chars) and then exeucte the following: $ ~/LazarusProjecten/bugs/findfirst/efn . It prints out only the first 255 characters of the current directory. (This issue poped up whilst investigating http://bugs.freepascal.org/view.php?id=24885)

Did you enable ansistrings and object pascal mode ? Because as it is displayed above, the program will use shortstrings, and they are limited to 255 chars.

Michael.

Tomas Hajny
to Michael Van Canneyt
Michael Van Canneyt wrote
On Sat, 31 Aug 2013, Bart wrote:

Hi,

Show quoted text 21 lines
> Before reporting this as a bug, can somebody confirm? > > program efn; > > uses sysutils; > > begin > writeln(expandfilename(paramstr(1))); > end. > > If I cd to a directory with a very long name (>255 chars) and then > exeucte the following: > $ ~/LazarusProjecten/bugs/findfirst/efn . > > It prints out only the first 255 characters of the current directory. > (This issue poped up whilst investigating > http://bugs.freepascal.org/view.php?id=24885) Did you enable ansistrings and object pascal mode ? Because as it is displayed above, the program will use shortstrings, and they are limited to 255 chars.

Well, I'm not sure if enabling ansistrings during program compilation changes anything, nor that the issue is related to ExpandFileName, because I believe that ParamStr (as provided in unit System) always returns shortstring values. Using "argv [1]" instead of ParamStr (1) should probably provide the expected result. I can imagine that we might add ansistring overloaded version (or unicodestring overloaded version in trunk).

Tomas

Bart
to Michael Van Canneyt: Did you enable ansistrings and object pascal mode ? Because as it is displayed above, the…
Michael Van Canneyt wrote
Did you enable ansistrings and object pascal mode ? Because as it is displayed above, the program will use shortstrings, and they are limited to 255 chars.

Yes (I typed the example from the top if my head): (ObjFpc mode should not matter though as long as {$H+} is specified?)

Here's my very long directory:

012345679]$ pwd
/home/bart/X/01DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD/012345679

Here's the program source:

 012345679]$ cat ~/LazarusProjecten/bugs/findfirst/efn.lpr
program efn;
{$mode objfpc}
{$H+}
uses sysutils;
var
  S: String;
  Len: Integer;
begin
  S := SysUtils.ExpandFileName(ParamStr(1));
  Len := Length(S);
  writeln(Format('%s [Length = %d]',[S,Len]));
end.

And this is what it outputs.

012345679]$ ~/LazarusProjecten/bugs/findfirst/efn . /home/bart/X/01DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD [Length = 255]
012345679]$

At some point a call is made to
Procedure getdir(drivenr:byte;var dir:ansistring); (rtl/inc/sysem.inc)

This then calls the ShortString version of GetDir() and puts the resulting ShortString back into the AnsiString.

Procedure getdir(drivenr:byte;Var dir:ansistring);
{ this is needed to also allow ansistrings, the shortstring version is
  OS dependent }
var
  s : shortstring;
begin
  getdir(drivenr,s);
  dir:=s;
end;

Bart

Tomas Hajny
to Bart
Bart wrote 58 lines
On 8/31/13, Michael Van Canneyt wrote: > Did you enable ansistrings and object pascal mode ? > Because as it is displayed above, the program will use shortstrings, and > they are limited to 255 chars. Yes (I typed the example from the top if my head): (ObjFpc mode should not matter though as long as {$H+} is specified?) Here's my very long directory: 012345679]$ pwd /home/bart/X/01DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD/012345679 Here's the program source: 012345679]$ cat ~/LazarusProjecten/bugs/findfirst/efn.lpr program efn; {$mode objfpc} {$H+} uses sysutils; var S: String; Len: Integer; begin S := SysUtils.ExpandFileName(ParamStr(1)); Len := Length(S); writeln(Format('%s [Length = %d]',[S,Len])); end. And this is what it outputs. 012345679]$ ~/LazarusProjecten/bugs/findfirst/efn . /home/bart/X/01DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD [Length = 255] 012345679]$ At some point a call is made to Procedure getdir(drivenr:byte;var dir:ansistring); (rtl/inc/sysem.inc) This then calls the ShortString version of GetDir() and puts the resulting ShortString back into the AnsiString. Procedure getdir(drivenr:byte;Var dir:ansistring); { this is needed to also allow ansistrings, the shortstring version is OS dependent } var s : shortstring; begin getdir(drivenr,s); dir:=s; end;

Oops, sorry, you're right - I was focusing the ParamStr part too much in my previous post without realizing that the dot in your example is not expanded by the shell, of course. :-( Passing the directory name directly on the command line would still give a similar issue.

Now, as you have already found out yourself too, it is not an issue with ExpandFileName only, but also with the overloaded version of GetDir returning ansistring but still limited to 255 characters. I could provide a workaround for ExpandFileName (using SysUtils.GetCurrentDir and basically replicating the implementation of System.GetDir under Windows except for using ansistrings), but fixing the ansistring overloaded version of System.GetDir sound as a more appropriate option to me.

Tomas

Bart
to Tomas Hajny
Tomas Hajny wrote 8 lines
Now, as you have already found out yourself too, it is not an issue with ExpandFileName only, but also with the overloaded version of GetDir returning ansistring but still limited to 255 characters. I could provide a workaround for ExpandFileName (using SysUtils.GetCurrentDir and basically replicating the implementation of System.GetDir under Windows except for using ansistrings), but fixing the ansistring overloaded version of System.GetDir sound as a more appropriate option to me.

I was unable to test under Windows, but because the offending code is in a generic inc file, I suspect it happens on Windows as well.

On Linux I saw several file related functions that seem to handle only shortstrings...

Should I file a bugreport?

Bart

Jonas Maebe
to Bart
Bart wrote 16 lines
On 8/31/13, Tomas Hajny wrote: > Now, as you have already found out yourself too, it is not an issue with > ExpandFileName only, but also with the overloaded version of GetDir > returning ansistring but still limited to 255 characters. I could provide > a workaround for ExpandFileName (using SysUtils.GetCurrentDir and > basically replicating the implementation of System.GetDir under Windows > except for using ansistrings), but fixing the ansistring overloaded > version of System.GetDir sound as a more appropriate option to me. I was unable to test under Windows, but because the offending code is in a generic inc file, I suspect it happens on Windows as well. On Linux I saw several file related functions that seem to handle only shortstrings... Should I file a bugreport?

This is all already fixed in the cpstrrtl branch.

Jonas

Tomas Hajny
to Bart: I was unable to test under Windows, but because the offending code is in a generic inc…
Bart wrote 18 lines
On 8/31/13, Tomas Hajny wrote: > Now, as you have already found out yourself too, it is not an issue with > ExpandFileName only, but also with the overloaded version of GetDir > returning ansistring but still limited to 255 characters. I could > provide > a workaround for ExpandFileName (using SysUtils.GetCurrentDir and > basically replicating the implementation of System.GetDir under Windows > except for using ansistrings), but fixing the ansistring overloaded > version of System.GetDir sound as a more appropriate option to me. > I was unable to test under Windows, but because the offending code is in a generic inc file, I suspect it happens on Windows as well. On Linux I saw several file related functions that seem to handle only shortstrings... Should I file a bugreport?

In general, it is a known fact that file system related functions provided by unit System are limited to shortstrings. From this point of view, GetDir is rather an exception (and admittedly rather unfortunate one considering the current state of implementation), because it provides an overloaded ansistring version. From this point of view, I would say that a bug report is indeed appropriate, but I'd limit it to GetDir for now (for the others like MkDir, etc., you could file a feature request at best).

Tomas

Bart
to Tomas Hajny
Tomas Hajny wrote 7 lines
In general, it is a known fact that file system related functions provided by unit System are limited to shortstrings. From this point of view, GetDir is rather an exception (and admittedly rather unfortunate one considering the current state of implementation), because it provides an overloaded ansistring version. From this point of view, I would say that a bug report is indeed appropriate, but I'd limit it to GetDir for now (for the others like MkDir, etc., you could file a feature request at best).

Jonas Maebe said:

This is all already fixed in the cpstrrtl branch.

If this applies to _all_ file operation functions, then maybe just wait? Fixing only GetDir makes little sense to me.

Bart

Tomas Hajny
to Bart
Bart wrote 15 lines
On 8/31/13, Tomas Hajny wrote: > In general, it is a known fact that file system related functions provided > by unit System are limited to shortstrings. From this point of view, > GetDir is rather an exception (and admittedly rather unfortunate one > considering the current state of implementation), because it provides an > overloaded ansistring version. From this point of view, I would say that a > bug report is indeed appropriate, but I'd limit it to GetDir for now (for > the others like MkDir, etc., you could file a feature request at best). Jonas Maebe said: > This is all already fixed in the cpstrrtl branch. If this applies to _all_ file operation functions, then maybe just wait? Fixing only GetDir makes little sense to me.

That probably depends on the level of urgency this issue has for you. Obviously, even higher level of urgency for you doesn't guarantee that somebody backports the functionality to fixes (the implementation in cpstrrtl branch mentioned by Jonas cannot be simply merged to fixes from trunk even after it gets to trunk which should hopefully happen soon - the basis might be the same, but some parts would need to be changed when backporting it to fixes). As I wrote - the other file and directory related functions and procedures have always had only shortstring interfaces, whereas with GetDir there has also been the ansistring version).

Tomas

Bart
to Tomas Hajny
Tomas Hajny wrote
That probably depends on the level of urgency this issue has for you.

ATM it does not happen in real world scenarios for me.

As I wrote - the other file and directory related functions and procedures have always had only shortstring interfaces, whereas with GetDir there has also been the ansistring version).

I would prefer waiting for _all_ IO functions to handle LongStrings (or any not_shortstring).
If I understand correctly this will happen in the 2.8 series then (which has the cpstring feature)?

(I suppose the curent limitation is documented somewhere?)

Bart

Marco van de Voort
to Bart

In our previous episode, Bart said:

Show quoted text 7 lines
> As I wrote - > the other file and directory related functions and procedures have > always had only shortstring interfaces, whereas with GetDir there has > also been the ansistring version). I would prefer waiting for _all_ IO functions to handle LongStrings (or any not_shortstring).

That was the original idea, removing the shortstring versions for not embedded targets, so that nobody accidentally could call shortstring versions. (and only find out runtime)

But that was deemed to confusing, so now both sets are back again.

Tomas Hajny
to Marco van de Voort
Marco van de Voort wrote 14 lines
In our previous episode, Bart said: > > As I wrote - > > the other file and directory related functions and procedures have > > always had only shortstring interfaces, whereas with GetDir there has > > also been the ansistring version). > > I would prefer waiting for _all_ IO functions to handle LongStrings > (or any not_shortstring). That was the original idea, removing the shortstring versions for not embedded targets, so that nobody accidentally could call shortstring versions. (and only find out runtime) But that was deemed to confusing, so now both sets are back again.

Well, this whole discussion is not about accidental calling of wrong version of anything but rather about getting support of the LFNs where needed. As pointed out by Jonas, the provided test program should work properly in cpstrrtl branch (even though the shortstring variants are still included there _in_addition_ to those providing full LFN support).

Tomas

Bart
to Marco van de Voort: In our previous episode, Bart said: That was the original idea, removing the shortstring…
Marco van de Voort wrote 5 lines
That was the original idea, removing the shortstring versions for not embedded targets, so that nobody accidentally could call shortstring versions. (and only find out runtime) But that was deemed to confusing, so now both sets are back again.

If I understand you correctly:
This would mean that (in the cpstr branch) calling any IO function with LongStrings (or the like) will NOT suffer from the problems the shortstring counterparts have?

Bart

Jonas Maebe
to Bart
Bart wrote
This would mean that (in the cpstr branch) calling any IO function with LongStrings (or the like) will NOT suffer from the problems the shortstring counterparts have?

Correct.

Jonas

Marco van de Voort
to Bart: If I understand you correctly: This would mean that (in the cpstr branch) calling any IO…

In our previous episode, Bart said:

Show quoted text 10 lines
> That was the original idea, removing the shortstring versions for not > embedded targets, so that nobody accidentally could call shortstring > versions. (and only find out runtime) > > But that was deemed to confusing, so now both sets are back again. If I understand you correctly: This would mean that (in the cpstr branch) calling any IO function with LongStrings (or the like) will NOT suffer from the problems the shortstring counterparts have?

Yes, several problems were fixed. Mostly in the past they were considered not worthwhile to fix (because it would only up from 255 to 260 chars).

Since in the unicode branch, the unicode functions are called that allow longer strings (from memory: 8192 straight, and more with \\.\ prepended?), it was decided to clean up all cases where there were shortstring only code paths (like getdir).