File path seems not compatible across windows and unix with save state

I’m using: SWI-Prolog version 8.3.3

  1. rdf_load from a folder /home/cocprd/cm/rdf3/ recursively.

  2. First compiled prolog code on windows using:
    swipl -o willie -c abc.pl

  3. copied willie to Linux, and run with:
    swipl -x willie

It seems converting file path to lower case.
It works fine if compiling into saved state on Linux.

Error occurred - the file does exist by the name of /home/cocprd/cm/rdf3/kb/cyberobject/blue/Document/001.cm
(Document instead of document)

`’/home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’’ does not exist
ERROR: In:
ERROR: [37] time_file(’/home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,_338)
ERROR: [36] rdf_db:open_input_if_modified(file(’’),‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,_378,_380,_382,_384,trig,[concurrent(1),…|…]) at /opt/prolog/lib/swipl/library/semweb/rdf_db.pl:1806
ERROR: [35] rdf_db:rdf_open_input(‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,file(’’),‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,_450,_452,_454,trig,[concurrent(1),…|…]) at /opt/prolog/lib/swipl/library/semweb/rdf_db.pl:1682
ERROR: [34] rdf_db:rdf_load_file((0xcd67530),’/home/cocprd/cm/rdf3/kb/cyberobject/blue/Document/001.cm’,‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,file(’’),‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,ip_app_load,[concurrent(1),…|…]) at /opt/prolog/lib/swipl/library/semweb/rdf_db.pl:1555
ERROR: [33] setup_call_catcher_cleanup(rdf_db:with_mutex(rdf_load_file,…),rdf_db:rdf_load_file((0xcd67530),’/home/cocprd/cm/rdf3/kb/cyberobject/blue/Document/001.cm’,‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,…,‘file:///home/cocprd/cm/rdf3/kb/cyberobject/blue/document/001.cm’,ip_app_load,…),_580,rdf_db:rdf_end_load((0xcd67530))) at /opt/prolog/lib/swipl/boot/init.pl:562
ERROR: [29] setup_call_catcher_cleanup(rdf_db:set_prolog_flag(agc_margin,0),rdf_db:rdf_load_noagc(’/home/cocprd/cm/rdf3/kb/cyberobject/blue/Document/001.cm’,ip_app_load,…),_660,rdf_db:set_prolog_flag(agc_margin,10000)) at /opt/prolog/lib/swipl/boot/init.pl:562
ERROR: [27] rdf_db:rdf_load(’/home/cocprd/cm/rdf3/kb/cyberobject/blue/Document/001.cm’,’<garbage_collected>’) at /opt/prolog/lib/swipl/library/semweb/rdf_db.pl:1470

True. Saved states are portable across platforms, but path names generally do not make sense and you thus need to avoid relying on them. There are more pitfalls, such as conditional compilation that may cause a state not to be suitable for the target platform. I don’t really see a solution to that. For the RDF store, the triples are not part of the state anyway and one should thus not load RDF while creating a saved program.

Thanks Jan.
First of all, I am not loading RDF into the saved state. RDF is being loaded at runtime using directory_member/3 and rdf_load/2.

Dig into it a bit more. Discovered the issue is with absolute_file_name/2,3 which is called by rdf_load/2:
On Windows:

?- absolute_file_name(’…/rdf3/kb/cyberobject/blue/Document/001.cm’, A,[]).
A = ‘e:/project/rdf3/kb/cyberobject/blue/document/001.cm’.

On Linux:

?- absolute_file_name(’…/rdf3/cyberobject/Document/001.cm’, X, []).
X = ‘/home/cocprd/cm/rdf3/cyberobject/Document/001.cm’.

As you have mentioned, there must be a conditional compilation for absolute_file_name/2,3. It breaks the portability here.

I don’t understand why it is needed to convert the case on path names. It seems to me that the issue of case on path names should be left to the underlying OS.

Lastly, I would like to argue that this need to be resolved. Most apps will read/write files and likely saved state portability will break in these cases unless stating only lower case path names are portable.

Because SWI-Prolog tries to keep absolute file names such that name equality can be used to test whether we are talking about the same file. That may have been a dubious choice.

How does a saved absolute file name affect your saved state though? Of course absolute file names typically have changed in the target environment and should not be saved in the first place (or at least, the saved path should not be accessed).

HI Jan,

I probably didn’t make myself clear.

I want to load rdf from a folder with sub-folders at runtime (part of initialization). I am using directory_member/3 to traverse the folder recursively, use rdf_load/2 to load the file with certain extensions.

The code snippet looks like:

ip_load_app_kb(Dir) :-
    foreach(directory_member(Dir, F, [extensions([cm, trig, ttl])]), 
          rdf_load(F, []).

% the Dir come from the command line option.
: - ip_load_app_kb(Argv).

Say, I want to load from folder:
in Windows: e:/project/app
In Linux: /home/cocprd/app

Under the above folder:
In Windows: e:/project/app/Document/001.cm
In Linux: /home/cocprd/app/Document/001.cm

Compile the code in windows. Run the saved state in Linux.

It fails because the path name become /home/cocprd/app/document/001.cm instead of /home/cocprd/app/Document/001.cm. Linux path name is case sensitive thus couldn’t locate the file to load.

No absolute file name is stored in saved state, nor any RDFs. The intent is to load some RDFs from a folder when starting the app.

Hopefully this is clear enough.

Thanks, as always, a lot for your help.

It is still not clear to me what is going wrong. Can you assemble a minimal program that I can really run?

One thing that comes to mind is the flag file_name_case_handling. Could it be that this is preserved in the state and thus set to the wrong value for Linux? I do not have access to a Windows machine right now …

If that is the problem, this flag probably needs to be added to the flags that should not be saved/restored in library(qsave).

Hi Jan,

The flag file_name_case_handling is what I am looking for. Thanks.

While setting the flag to case_sensitive, swipl -o $$ -c $$ splits these messages:

.....
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/date.pl
Now c:/program files/swipl/library/shell.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/error.pl
Now c:/program files/swipl/library/lists.pl
Now c:/program files/swipl/library/pairs.pl
Now c:/program files/swipl/library/lists.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/error.pl
Now c:/program files/swipl/library/lists.pl
Now c:/program files/swipl/library/lists.pl
Now c:/program files/swipl/library/process.pl
Now c:/program files/swipl/library/apply.pl
Now c:/program files/swipl/library/lists.pl
Now c:/program files/swipl/library/system.pl
% Disabled autoloading (loaded 17 files)
% Disabled autoloading (loaded 0 files)

In addition, the Disabled autoloading (loaded N files).
N is different with flag file_name_case_handling=case_sensitive vs the default flag.

But it seems working okay.

Thank you!

Nan

Thanks for the update. Pushed a fix that disables saving this flag, so the state starts with the OS default rather than the OS default that created the state.

1 Like

COOOOL! Thanks!