INQUIRE finds a non-existing file

Hi!

Last week I forgot to fill a CHARACTER*4 with the year ‘2008’.
As a result, the directory where my application was looking for its input
was a bogus string containing two consecutive slashes and which obviously did not exist.
Nevertheless, INQUIRE tells me that that file does exist and my program proceeds and crashes trying to read it…
Below you’ll find a narrowed down piece of code.
If you replace the part '/home/dijkva/'by an existing directory
on your machine, then you’ll probably get the same result as I get:
the first attempt via the main program tells you that ‘myfile’ does not exist.
The second attempt however suggests successful probing!
I am running:

pgf90 6.1-4 32-bit target on x86-64 Linux
Copyright 1989-2000, The Portland Group, Inc. All Rights Reserved.
Copyright 2000-2006, STMicroelectronics, Inc. All Rights Reserved.

I did not use any fancy compile-switches. Just “pgf90”.

Is this a bug in the compiler?
When compiled with e.g. g95 both calls tell me that the file does not exist.

Regards,


Arjan

MODULE LibUtil
IMPLICIT NONE
PRIVATE
PUBLIC :: FileExists,MyRoutine
CONTAINS

   FUNCTION FileExists(Directory,FName)
   CHARACTER(*), INTENT(INOUT) :: FName,Directory
   LOGICAL :: FileExists,DumLog
   CHARACTER(256) :: MyString
   MyString = TRIM(Directory)//TRIM(FName)
   WRITE(*,'(A)') 'Just before it happens... "'//TRIM(MyString)//'"'
   INQUIRE(FILE=TRIM(MyString),EXIST=DumLog)
   FileExists = DumLog
   END FUNCTION FileExists

   SUBROUTINE MyRoutine()
   CHARACTER(256) :: FName,Directory
   LOGICAL :: DumLog
   CHARACTER :: YearStr*4
   FName = 'myfile'
!   WRITE(YearStr,'(I4)') 2008  ! this is the line that I forgot to code...
   Directory = '/home/dijkva/' // YearStr // '/'
   DumLog = FileExists(Directory,FName)
   WRITE(*,*) DumLog
   END SUBROUTINE MyRoutine

END MODULE LibUtil

   PROGRAM Test
   USE libutil
   IMPLICIT NONE
   CHARACTER(256) :: Directory,FName
   LOGICAL :: DumLog
   Directory = '/home/dijkva//'
   FName = 'myfile'
   DumLog = FileExists(Directory,FName)
   WRITE(*,*) DumLog
   CALL MyRoutine()
   END PROGRAM Test

[/code]

Hi Arjan,

It’s not compiler bug. Since YearStr in uninitialized, it can contain random garbage. In 32-bits, it happens to be “\0” so the filename turns into a legal file name. If we also compile it 64-bits, then the garbage gets translated into " " and the inquire fails.

Example:

arroyo:/tmp/qa% pgf90 -o test test.f90 -V6.1-7 -tp k8-32
arroyo:/tmp/qa% test
Just before it happens... "//tmp/qa//myfile"
  T
Just before it happens... "//tmp/qa//myfile"
  T
arroyo:/tmp/qa% pgf90 -o test test.f90 -V6.1-7 -tp k8-64
arroyo:/tmp/qa% test
Just before it happens... "//tmp/qa//myfile"
  T
Just before it happens... "//tmp/qa/    /myfile"
  F

Hope this helps,
Mat

It’s not compiler bug. Since YearStr in uninitialized, it can contain random
garbage. In 32-bits, it happens to be “\0” so the filename turns into a legal
file name. If we also compile it 64-bits, then the garbage gets translated
into " " and the inquire fails.


Sorry, Mat, but I don’t understand your explanation.
To which file do you suggest that the following string refers?

/home/dijkva/\0/myfile

This is what would result if in my sample YearStr is replaced by “\0”.
I can hardly imagine that this will be something meaningful.

Regards,


Arjan

“\0” is short-hand for the NULL character (i.e. the value 0 not the character “0”) which would not be concatenated.

  • Mat

Directory /home/dijkva/ does not contain a file named “myfile”!
That file is located in /home/dijkva/2008/ but I had forgotten to include the
year as a string in the path and therefore INQUIRE should not have
confirmed existence in that wrong directory!

And: doesn’t it matter if there are redundant slashes in a pathname,
as in /home/dijkva//myfile ?

Regards,


Arjan

Hi Arjan,

Sorry, I did a poor job of explaining.

Directory /home/dijkva/ does not contain a file named “myfile”!

Correct, but by inadvertently adding a NULL character in the middle of the string, you’re actually inquiring if “/home/dijkva/” exists not /home/dijkva/myfile". For example, when I change the root directory to a non-existent directory, the inquire fails as expected.

arroyo:/tmp/qa% test
Just before it happens... "//tmp/qa//myfile"
  F
Just before it happens... "//tmp/nothere//myfile"
  F

Unfortunately, using uninitialized variables can lead to unpredictable results.

And: doesn’t it matter if there are redundant slashes in a pathname,
as in /home/dijkva//myfile ?

No, Linux doesn’t care how may slashes there are.

  • Mat

by inadvertently adding a NULL character in the middle of the string, you’re
actually inquiring if “/home/dijkva/” exists


Ah!

Thanks!
So I added a string-terminator (or something similar) instead of a string?
I am still a bit puzzled by the fact that I can print a string with
a NULL character in the middle as if nothing is wrong.
Maybe I was (am) hoping that this would be shown some way when I print
that string, e.g. by having the string printed in 2 pieces or some other sign
of evidence. Apparently not the case.
Thanks again!


Arjan

Hi Arjan,

The difference is because INQUIRE’s file name needs to be turned into a C null-terminated character string in order to interface with the OS function that checks if the file exists. A Fortran string does not use null-terminator so the whole string is printed.

Hope this helps,
Mat