Stdlib: API for file system operations: directory manipulation

Created on 16 Jul 2020  Â·  39Comments  Â·  Source: fortran-lang/stdlib

So, following the suggestion in #201, let's start to discuss file system access API. In order to keep it focused, I'd suggest to start with the directory related operations first. My proposal:

open_directory(dirname, dirdesc, status): Opens a directory and returns a descriptor

type(dirdesc_t): Type containing the data of an opened directory

dirdesc_t%get_next(): Returns the next entry in the open directory or "" if
there are no more entries.

make_directory(dirname, parents, status): Makes a directory. If parents is .true.
also parent directories are created in case they do not exist yet.

remove_directory(dirname, content, status): Removes a directory. If content is
.true. also the directory content is removed (recursive delete).

change_directory(dirname, status): Changes to the given directory

get_working_dir() -> char(:), allocatable: Returns the current working directory.

is_dir(fname) -> logical: GIve .true. if fname is a directory.

A few notes:

  • The functionality above can be easily realized with a libc-interface (should work on all POSIX systems) and a bit of C-code. The big question is Windows, as I have no clue how to implement this functionality on WIndows.

  • As for error handling we could have a status argument. I'd argue for having a derived type type(status_t) containg the result of the operation (OK/Error) and a string with the error message in case of error. Whether the status argument should be optional or not is open for discussions.

Most helpful comment

Since this is related to #201, I want to explain the rational why I prefer to rely on standard types and no type bound procedures for low level operations:

In Fortran, one cannot chain function calls (and array access), so an object oriented approach will result in something like:

type(t_path) :: filename
filename = getcwd()
call filename%join('my_file.ext)
print*, filename%islink()

while the functional/procedural way gives:

print*, islink(join(getcwd(),'my_file.ext'))

I acknowledge that this is not the most elaborate example, but in generally I think that a procedural approach is often more natural for Fortran.

All 39 comments

We should survey Python, Rust, Julia, Matlab, etc. to see what API they use for this.

That looks like a good start :). I would like to add though:

dirdesc_t%get_first() - to get the first entry or to restart the search.

Should it be possible to specify a filter?

As for Windows, as that is the main OS I work with, I might give that a
try. While the function names differ, the functionality is largely the same.

Wrt the type of the various arguments such as dirname, these would be
simple strings? Then I suggest we use the forward slash as the directory
separator - it is accepted by all the major OSs and anything else can be
solved inside the implementation (notably the C bit).

Regards,

Arjen

Op do 16 jul. 2020 om 23:01 schreef Bálint Aradi notifications@github.com:

So, following the suggestion in #201
https://github.com/fortran-lang/stdlib/issues/201, let's start to
discuss file system access API. In order to keep it focused, I'd suggest to
start with the directory related operations first. My proposal:

open_directory(dirname, dirdesc, status): Opens a directory and returns a
descriptor

type(dirdesc_t): Type containing the data of an opened directory

dirdesc_t%get_next(): Returns the next entry in the open directory or ""
if
there are no more entries.

make_directory(dirname, parents, status): Makes a directory. If parents
is .true.
also parent directories are created in case they do not exist yet.

remove_directory(dirname, content, status): Removes a directory. If
content is
.true. also the directory content is removed (recursive delete).

change_directory(dirname, status): Changes to the given directory

get_working_dir() -> char(:), allocatable: Returns the current working
directory.

is_dir(fname) -> logical: GIve .true. if fname is a directory.

A few notes:

-

The functionality above can be easily realized with a libc-interface
(should work on all POSIX systems) and a bit of C-code. The big question is
Windows, as I have no clue how to implement this functionality on WIndows.
-

As for error handling we could have a status argument. I'd argue for
having a derived type type(status_t) containg the result of the
operation (OK/Error) and a string with the error message in case of error.
Whether the status argument should be optional or not is open for
discussions.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220, or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR3UW3EBFNYXV2PRHWTR35TDHANCNFSM4O45YWQA
.

I think we should start with just the file path bit. See the Rust library, or the Haskell library.

Also, I don't particularly like the manual iterator design for open_directory. I'd much rather have a function get_contents(directory) -> type(file_path), allocatable :: paths(:). To me, open_directory and dirdesc%get_next() smacks of object-oriented assembly, in an attempt to satisfy primitive obsession.

I'd much rather have a function get_contents(directory) -> type(file_path), allocatable :: paths(:)

:+1: +1

Also, I see inconsistent naming, e.g. is_dir() and dirdesc_t, but change_directory and remove_directory. I like shorter names if they're common enough. In this case, I think they are. What do you think about:

  • change_directory -> chdir
  • make_directory -> mkdir
  • remove_directory -> rmdir
  • get_working_dir -> get_cwd or getcwd

Python API reference: https://docs.python.org/3/library/os.html

I think we should start with just the file path bit. See the Rust library, or the Haskell library.

Should this be a separate thread? I think in this one we discuss only directory stuff, plus I think most directory operations here are independent of file path.

@everythingfunctional The interface here is basically a 1-1 mapping of the libc API, which also uses an iterator. (Works in Rust also similarly) But sure, if we have a decent file path type, we could have a convenience funtion on top of it which returns an allocatable array instead.

@milancurcic Although I'd be very happy to go with Pythons naming convention, it would not be consistent with Fortrans recent naming strategy (e.g. execute_command_line instead of exec or even command_argument_count). For sake of adoption, I'd probably prefer the style which is more Fortran like, even if I am not big fan of it. We could use _dir everywhere to make it more consistent and somehwat shorter, though: create_dir (or make_dir), remove_dir, change_dir, etc...

I see. In that case the question becomes one of philosophy for stdlib. Does stdlib provide lots of low level stuff for people to build abstractions on top of, or does it aim to provide useful abstractions and ergonomic APIs?

@everythingfunctional I agree, it is a philosophical question. And given the traditional reluctance of Fortran to delve into the depths of the underlying operating system, a higher level solution would indeed be probably more appropriate.

If we return an array, we have to decide on the element type. I see 3 different options:

  • characters of some fixed length (e.g. max path length size on the system, or similar)
  • a string derived type (offering variable string sizes and maybe also some string capabilties)
  • a path derived type (offering path manipulation and path-query capabilties).

I am working on Option 3 at the moment, but as discussed in #224, we should decide, whether and if yes how many derived types we want to impose on the users of stdlib...

@everythingfunctional regarding the goal of stdlib, I consider it both:

  • provide reusable low level functionality that gets the job done and people can use it to build more high level interfaces, or just use it directly; ideally these are just raw functions / subroutines that do not use derived types
  • nicely designed high level interfaces (perhaps OO based) that use the low level blocks; this is designed to be ergonomic and can use derived types or other OO features

That way everybody gets what they want, both people who prefer more OO, as well as people who prefer more direct low level API.

In that case, I think the original proposal is perfectly suitable as low-level building blocks. It wouldn't be difficult to build a more ergonomic API using them.

Since this is related to #201, I want to explain the rational why I prefer to rely on standard types and no type bound procedures for low level operations:

In Fortran, one cannot chain function calls (and array access), so an object oriented approach will result in something like:

type(t_path) :: filename
filename = getcwd()
call filename%join('my_file.ext)
print*, filename%islink()

while the functional/procedural way gives:

print*, islink(join(getcwd(),'my_file.ext'))

I acknowledge that this is not the most elaborate example, but in generally I think that a procedural approach is often more natural for Fortran.

@MarDiehl I am a big fan of simple functions / subroutines also over object oriented approach. In general, we can have both to satisfy everybody.

@MarDiehl Yes, your reasoning is very convincing and indeed, that approach fits definitely better to Fortran.

But giving the suggested directory API above, which part would you propose to be change? The only type bound procedure we have so far is get_next(this) so far. As this changes the internal state of the directory, it must be implemented as a subroutine, so we have the choice between

call get_next(mydir, nextentry)

and

call mydir%get_next(nextentry)

I don't know, whether there is any esthetic difference between the two....

If you refer to the type(path) suggestion, I am with you, that we should rather use intrinsic types (e.g. allocatable chars here) whenever possible.

@milancurcic , @MarDiehl As for being "fortranic": Then getcwd() should be rather get_working_dir() or similar, as especially recently introduced Fortran functions handling the environment (e.g. execute_command_line, command_argument_count tend to be rather verbose than abbreviated. I am not saying, that we should be that verbose, but I'd propose to introduce names which are more consistent with the naming philosophy of the already existing language.

Actually, if you have a type-bound procedure, then you can use both forms
:). o it will be down to taste then.

Op do 30 jul. 2020 om 16:44 schreef Bálint Aradi notifications@github.com:

@MarDiehl https://github.com/MarDiehl Yes, your reasoning is very
convincing and indeed, that approach fits definitely better to Fortran.

But giving the suggested directory API above, which part would you propose
to be change? The only type bound procedure we have so far is
get_next(this) so far. As this changes the internal state of the
directory, it must be implemented as a subroutine, so we have the choice
between

call get_next(mydir, nextentry)

and

call mydir%get_next(nextentry)

I don't know, whether there is any esthetic difference between the two....

If you refer to the type(path) suggestion, I am with you, that we should
rather use intrinsic types (e.g. allocatable chars here) whenever possible.

@milancurcic https://github.com/milancurcic , @MarDiehl
https://github.com/MarDiehl As for being "fortranic": Then getcwd()
should be rather get_working_dir() or similar, as especially recently
introduced Fortran functions handling the environment (e.g.
execute_command_line, command_argument_count tend to be rather verbose
than abbreviated. I am not saying, that we should be that verbose, but
I'd propose to introduce names which are more consistent with the naming
philosophy of the already existing language.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-666414532,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YRZ5RMFWDCVYSOZPLGDR6GBMRANCNFSM4O45YWQA
.

@aradi

what about an interface like the following:

function list_directory(path)

    character(len=*), intent(in)  :: path
    character(len=:), allocatable, dimension(:) :: list_directory
    ...

end function list_directory

this would simply return a array of strings containing the file names, an optional argument could specify the search order (creation time, name). This is similar go https://docs.python.org/2/library/os.html#os.listdir, again with the drawback that Fortran has no list type and we need to use an array.

I don't think that works in Fortran, I think you have to use a derived type to have an array of strings, like I did here:

https://github.com/fortran-lang/fpm/blob/fcb7f675a8203f0ab518b20e9e11ee6dd49c3186/fpm/src/fpm.f90#L78

I don't think that works in Fortran, I think you have to use a derived type to have an array of strings, like I did here:

https://github.com/fortran-lang/fpm/blob/fcb7f675a8203f0ab518b20e9e11ee6dd49c3186/fpm/src/fpm.f90#L78

It works. You just need to figure out the maximum length among all strings and the number of strings:

allocate(character(len=max_len)::list_directory(N_files))

Implementing such a function is of course a little bit cumbersome, but the advantage of stdlib is that it has to be done only once.

Ah I see. Ok, that can be a possibility. A bit wasteful, but simpler, and perhaps even more performing than the allocatable in allocatable approach.

I use an interface similar to what is being described, and looking over the list, three more that I find I use extensively are
one for getting the current scratch directory by assuming it is set by $TEMPDIR, $TMP, $TEMP or /tmp; but it would be nice to get what opening a Fortran SCRATCH file is using; something to set what that directory is; and when getting a directory listing as a standard array if you also want to return the length, which can increase processing speed versus trim() and also lets you handle outliers like trailing spaces in the name (an alternative is adding a null character to the name like C). I happen to use the prefix system_ for just about anything that requires an ISO_C_BINDING and is calling a "standard" library; but have no problem with the names above, except that some of the simpler ones like chdir, mkdir, ... are often common extensions so you have the potential problem of referring to the extensions if you forget the USE statement, and/or confusion over which one is being called for those familiar with the extention.

For reference my names are:

833 get_tmp (3m_io) - [M_io] Return the name of the scratch directory(LICENSE:PD)
835 system_dir (3m_io) - [M_io] return filenames in a directory matching specified wildcard string(LICENSE:PD)
1018 system_getcwd (3m_system) - [M_system] call getcwd(3c) to get the pathname of the current working directory(LICENSE:PD)

1016 system_chdir (3m_system) - [M_system] call chdir(3c) from Fortran to change working directory(LICENSE:PD)
1019 system_mkdir (3m_system) - [M_system] call mkdir(3c) to create a new directory(LICENSE:PD)
1024 system_rewinddir (3m_system) - [M_system] call rewinddir(3c) to rewind directory stream(LICENSE:PD)
1031 system_isdir (3m_system) - [M_system] checks if argument is a directory path(LICENSE:PD)
1036 system_closedir (3m_system) - [M_system] close a directory stream by calling closedir(3c)(LICENSE:PD)
1043 system_opendir (3m_system) - [M_system] open directory stream by calling opendir(3c)(LICENSE:PD)
1047 system_readdir (3m_system) - [M_system] read a directory using readdir(3c)(LICENSE:PD)

PS: setting and querying where the scratch files go is not an issue for most programs, but can be a big issue due to performance and space issues when huge scratch files are requred in HPC appiications. I but some notes about that and some of the major portability problems concering scratch files on Blevin's Fortran WIKI page a long time ago.

@MarDiehl Yes, the allocated character array is as "fortranic" as only possible. :smile: Three remarks:

  • It is not that cumbersome to implement. The algorithm would have first to loop over all entries of a directory anyway (to find out how many there are) and then once more to put their names in the allocated array. In he first loop one can then also easily determine the max file name length.

  • Consumers would have to trim() the entries to find out the true file names. As long as the file names are just passed to intrinsic statements, like open, this is OK, as open automatically trims the passed character variable, but it may be still error prone and annoying if the user tries to manipulate the file name (e.g. checking whether it ends with a given suffix, or when an additional suffix should be added to the file name).

  • Should other file manipulation commands automatically trim character variables containing file names? It would be quite convenient (one would spare a lot of trim()s and 100% compatible with current Fortran. However it also would inherit consequence, that it is impossible to treat file names ending on whitespaces, or to be more precise, impossible to distinguish between file names differing only in the nr. of whitespaces at the end of their file names. (But, since we can not fix that problem in the existing open statement anyway, probably the best thing is to have a "consistently broken" implementation of the other features in stdlib anyway...)

@aradi:
1) True, it is actually not that bad. I do the same in the split function.
2) Yes, further manipulation would always require a trim. At least for all the os/os_path functions I would do that for all intent(in) strings
3) This is a important point I totally missed. The hack used for URL encoding (replace by + or %20) is quite ugly. I agree with you that we should simply document this behavior since we cannot change the behavior of trim/open anyways. Better we have a simple and easy to user function that works for 99% of the users than something complicated that handles corner cases but is hard to use for the vast majority. Spaces on the shell are anyways a nightmare and trailing spaces are even difficult for graphical file explorers.

I have picked up work on the Windows version again. While I made good
progress over the weekend, I am not there yet. The most important issue I
am currently facing is this:
The implementation stops via ERROR STOP when a function or routine
encounters an error. This prevents the user from taking corrective action.
It also prevents the program from ignoring the problem of course. Is this
what we want? I can imagine a sort of dual API, much like the OPEN
statement. If you do not provide an argument to store any error condition
in, then the ERROR STOP action is taken. Otherwise it is left to the
programmer to properly deal with the error. Something along these lines:

subroutine chdir(path, error)

character(len=*), intent(in) :: path
logical, intent(out), optional :: error
if ( present(error) ) then
    error = .false.
endif
if(chdir_c(f_c_string(path)) /= 0_C_INT) then
  if ( present(error) ) then
     error = .true.
  else
     error stop 'chdir: cannot change directory'
 endif

endif

The test program is currently also using the routine symlink. As on Windows
links have a very different purpose, the current implementation returns an
error and therefore fails. I have introduced a mechanism to check the
operating system and so we can avoid a call to symlink we know is going to
fail. But that only avoids the above issue.

Some other things worth mentioning:

  • I found out why CMake was not creating the appropriate makefiles on
    Windows (spaces in the path to the compiler, yes, those abominable spaces).
    In fact the CMakeLists.txt file at the highest level can be made much
    simpler. The result: it works on all three Windows platforms (plain
    Windows, Cygwin and MinGW)
  • I do not think the test program should rely on the present of a Python
    installation :). The use it currently makes of it is very limited and
    easily done in Fortran.
  • It may be useful to know the type of OS, so that is now (in my copy of
    the repository) caught via a bit of CMake manipulation.

Regards,

Arjen

Op vr 31 jul. 2020 om 13:17 schreef Martin Diehl notifications@github.com:

@aradi https://github.com/aradi:

  1. True, it is actually not that bad. I do the same in the split
    function.
  2. Yes, further manipulation would always require a trim. At least for
    all the os/os_path functions I would do that for all intent(in) strings
  3. This is a important point I totally missed. The hack used for URL
    encoding (replace by + or %20) is quite ugly. I agree with you that we
    should simply document this behavior since we cannot change the behavior of
    trim/open anyways. Better we have a simple and easy to user function
    that works for 99% of the users than something complicated that handles
    corner cases but is hard to use for the vast majority. Spaces on the shell
    are anyways a nightmare and trailing spaces are even difficult for
    graphical file explorers.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-667070268,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR4W7F5UDOVL4EEJO7TR6KR6FANCNFSM4O45YWQA
.

Oh, and one thing I forgot: on Windows the usual character used to separate
directory names in a path is the backslash, not the forward slash. While a
forward slash is perfectly acceptable (in most cases anyway and certainly
in Fortran programs), I can imagine people will expect a "\" to work when
splitting up a path name.

Regards,

Arjen

Op ma 7 sep. 2020 om 11:10 schreef Arjen Markus arjen.markus895@gmail.com:

I have picked up work on the Windows version again. While I made good
progress over the weekend, I am not there yet. The most important issue I
am currently facing is this:
The implementation stops via ERROR STOP when a function or routine
encounters an error. This prevents the user from taking corrective action.
It also prevents the program from ignoring the problem of course. Is this
what we want? I can imagine a sort of dual API, much like the OPEN
statement. If you do not provide an argument to store any error condition
in, then the ERROR STOP action is taken. Otherwise it is left to the
programmer to properly deal with the error. Something along these lines:

subroutine chdir(path, error)

character(len=*), intent(in) :: path
logical, intent(out), optional :: error
if ( present(error) ) then
    error = .false.
endif
if(chdir_c(f_c_string(path)) /= 0_C_INT) then
  if ( present(error) ) then
     error = .true.
  else
     error stop 'chdir: cannot change directory'
 endif

endif

The test program is currently also using the routine symlink. As on
Windows links have a very different purpose, the current implementation
returns an error and therefore fails. I have introduced a mechanism to
check the operating system and so we can avoid a call to symlink we know is
going to fail. But that only avoids the above issue.

Some other things worth mentioning:

  • I found out why CMake was not creating the appropriate makefiles on
    Windows (spaces in the path to the compiler, yes, those abominable spaces).
    In fact the CMakeLists.txt file at the highest level can be made much
    simpler. The result: it works on all three Windows platforms (plain
    Windows, Cygwin and MinGW)
  • I do not think the test program should rely on the present of a Python
    installation :). The use it currently makes of it is very limited and
    easily done in Fortran.
  • It may be useful to know the type of OS, so that is now (in my copy of
    the repository) caught via a bit of CMake manipulation.

Regards,

Arjen

Op vr 31 jul. 2020 om 13:17 schreef Martin Diehl <[email protected]

:

@aradi https://github.com/aradi:

  1. True, it is actually not that bad. I do the same in the split
    function.
  2. Yes, further manipulation would always require a trim. At least
    for all the os/os_path functions I would do that for all intent(in)
    strings
  3. This is a important point I totally missed. The hack used for URL
    encoding (replace by + or %20) is quite ugly. I agree with you that
    we should simply document this behavior since we cannot change the behavior
    of trim/open anyways. Better we have a simple and easy to user
    function that works for 99% of the users than something complicated that
    handles corner cases but is hard to use for the vast majority. Spaces on
    the shell are anyways a nightmare and trailing spaces are even difficult
    for graphical file explorers.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-667070268,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR4W7F5UDOVL4EEJO7TR6KR6FANCNFSM4O45YWQA
.

@arjenmarkus sorry for the late response, I've been busy with other things.
1) error handling: I have a branch with an optional stat argument. If that is given, it's return value can be used for checking the success of a function. Otherwise, error stop is called if something goes wrong. This behavior is similar to the behavior of standard language featurs.
2) windows path handling: We can make set the parameter defining the path separator depending on the OS. That would leave the question if there should be a standardize function (i.e. all user input with / would be translated to \ on Windows). In python, there are actually two implementation to handle these subtle differences (posixpath/ntpath)
3) Is there a difference between "real windows" and MingGW regarding the expected behavior on Windows?
4) I will continue to work on the library on the weekend. Should we exchange ideas via skype or zoom then? I think that would be easier.

No problem, I have been busy too.

The question of distinguishing "real/plain Windows" from MinGW is not very
simple to answer. If you use the console it is rather unixy in behaviour,
but MinGW tries to be windowish. I guess we can refine this later, should
differences become relevant in the context of a Fortran program trying to
cooperate with the operating system.

As for exchanging ideas via Zoom or Skype, that would normally be quite
convenient, but I cannot plan ahead right now (unforeseen and unforeseeable
events in my family).

Regards,

Arjen

Op ma 7 sep. 2020 om 16:18 schreef Martin Diehl notifications@github.com:

@arjenmarkus https://github.com/arjenmarkus sorry for the late
response, I've been busy with other things.

  1. error handling: I have a branch with an optional stat argument. If
    that is given, it's return value can be used for checking the success of a
    function. Otherwise, error stop is called if something goes wrong.
    This behavior is similar to the behavior of standard language featurs.
  2. windows path handling: We can make set the parameter defining the
    path separator depending on the OS. That would leave the question if there
    should be a standardize function (i.e. all user input with / would be
    translated to \ on Windows). In python, there are actually two
    implementation to handle these subtle differences (posixpath/ntpath)
  3. Is there a difference between "real windows" and MingGW regarding
    the expected behavior on Windows?
  4. I will continue to work on the library on the weekend. Should we
    exchange ideas via skype or zoom then? I think that would be easier.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-688355276,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YRYJM7BHBK4SB6NVJVDSETTSZANCNFSM4O45YWQA
.

ok, then it's best if you contact me via email: m.[email protected] if you have time.

WIll do, asap - I should be able to find time, if nothing else as a
distraction.

Regards,

Arjen

Op di 8 sep. 2020 om 08:17 schreef Martin Diehl notifications@github.com:

ok, then it's best if you contact me via email: m.[email protected] if you
have time.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-688642510,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR32SPX7BXSVA63VBQ3SEXD6HANCNFSM4O45YWQA
.

I am really happy about the implementations by @MarDiehl ! You should come up with a Draft PR to discuss details there!

The status at this moment:

  • The code is working for Linux, plain Windows and Cygwin
  • I have the CMake build system working for three Windows environments -
    plain Windows, Cygwin and MinGW. MSYS is on its way, now that I understand
    the difference between MinGW and MSYS.
  • The implementation uses ERROR STOP in a number of places without the
    program having a chance to catch it. That is something I want to get rid of
  • return a "magic" number instead.
  • The code could do with some clean-up in places and there are a few
    issues with forward and backward slashes.
  • The code is missing a few useful features: getting the file and
    directory names is the most pressing one.

But I agree: it is definitely in a useable state.

@MarDiehl, what do you think? (Note: I need to consolidate and submit the
latest stuff :))

Op wo 7 okt. 2020 om 14:07 schreef Sebastian Müller <
[email protected]>:

I am really happy about the implementations by @MarDiehl
https://github.com/MarDiehl ! You should come up with a Draft PR to
discuss details there!

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-704890386,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR5XMWY7PBXNKARW4RDSJRKW3ANCNFSM4O45YWQA
.

@arjenmarkus Sorry for the late reply, I started a new appointment and simply ignored all emails that were not directly related to my old and new work. I'm now back at this

Ah, good to see you're back :). i have been busy getting the test program
to work on all platforms I have access to (and as it turns out, I have
access to five different platforms, not four, as MinGW and MSYS are related
but in some ways entirely different platforms).

Op wo 7 okt. 2020 om 14:45 schreef Martin Diehl notifications@github.com:

@arjenmarkus https://github.com/arjenmarkus Sorry for the late reply, I
started a new appointment and simply ignored all emails that were not
directly related to my old and new work. I'm now back at this

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-704910095,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR2YXIVA4C5ALFLFDSDSJRPE5ANCNFSM4O45YWQA
.

Hm, a slight but rather nasty problem occurred: the Intel Fortran version
on Windows now stops suddenly in the getsize function. It works fine in a
reduced program.

Op wo 7 okt. 2020 om 15:00 schreef Arjen Markus arjen.markus895@gmail.com:

Ah, good to see you're back :). i have been busy getting the test program
to work on all platforms I have access to (and as it turns out, I have
access to five different platforms, not four, as MinGW and MSYS are related
but in some ways entirely different platforms).

Op wo 7 okt. 2020 om 14:45 schreef Martin Diehl <[email protected]

:

@arjenmarkus https://github.com/arjenmarkus Sorry for the late reply,
I started a new appointment and simply ignored all emails that were not
directly related to my old and new work. I'm now back at this

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-704910095,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR2YXIVA4C5ALFLFDSDSJRPE5ANCNFSM4O45YWQA
.

I have isolated the problem in a small test program - see the attachment.
It occurs with Intel Fortran 18 on both Windows and Linux. Since this
hinders the further development of this library, I am going to resort to
using a C function instead (like for the creation/modification/access times
for files).

Regards,

Arjen

Op wo 7 okt. 2020 om 21:16 schreef Arjen Markus arjen.markus895@gmail.com:

Hm, a slight but rather nasty problem occurred: the Intel Fortran version
on Windows now stops suddenly in the getsize function. It works fine in a
reduced program.

Op wo 7 okt. 2020 om 15:00 schreef Arjen Markus [email protected]

:

Ah, good to see you're back :). i have been busy getting the test program
to work on all platforms I have access to (and as it turns out, I have
access to five different platforms, not four, as MinGW and MSYS are related
but in some ways entirely different platforms).

Op wo 7 okt. 2020 om 14:45 schreef Martin Diehl <[email protected]

:

@arjenmarkus https://github.com/arjenmarkus Sorry for the late reply,
I started a new appointment and simply ignored all emails that were not
directly related to my old and new work. I'm now back at this

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-704910095,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR2YXIVA4C5ALFLFDSDSJRPE5ANCNFSM4O45YWQA
.

program stdlib_test

!use os_path

implicit none
integer :: unit
logical :: error

integer :: ierr
integer :: sz

character(len=:), allocatable, dimension(:) :: split_str
character(len=:), allocatable :: startdir

print*, "Start"

inquire( file = 'testtxt', size = sz, iostat = ierr )
print*, "Size: ", sz

print, "local_getsize('test.txt'): ", local_getsize('test.txt')
!print
, "getsize('test.txt'): ", getsize('test.txt')
print*, "Done"

contains
function local_getsize(path)

!integer(int64)               :: getsize
integer                      :: local_getsize
integer                      :: sz
character(len=*), intent(in) :: path
integer                      :: ierr

!write(*,*) '>>', path
call local_getsize_routine( path, sz, ierr )
!inquire( file = path, size = sz, iostat = ierr )

local_getsize = sz
if ( ierr /= 0 ) then
   local_getsize = -1
endif
!write(*,*) '>>', getsize

end function local_getsize

subroutine local_getsize_routine( path, sz, ierr )
character(len=*), intent(in) :: path
integer, intent(out) :: sz
integer, intent(out) :: ierr

inquire( file = path, size = sz, iostat = ierr )

end subroutine local_getsize_routine

end program stdlib_test

Hi @arjenmarkus , I think the above code will work if you use inquire after opening the file:

subroutine local_getsize_routine( path, sz, ierr )
    character(len=*), intent(in) :: path
    integer, intent(out)         :: sz
    integer, intent(out)         :: ierr
    integer :: fh

    open(newunit=fh, file = path, iostat = ierr )
    if (ierr /=0 ) return
    inquire( unit=fh, size = sz, iostat = ierr )
    close(fh)
end subroutine local_getsize_routine

You're right - that does seem to do the trick. I have tested it on both
Windows and Linux.

The only drawback is that the program should have read access to the file
in that case, but the implementation is straightforward.

Op zo 11 okt. 2020 om 13:25 schreef Laurence Kedward <
[email protected]>:

Hi @arjenmarkus https://github.com/arjenmarkus , I think the above code
will work if you use inquire after opening the file:

subroutine local_getsize_routine( path, sz, ierr )
character(len=*), intent(in) :: path
integer, intent(out) :: sz
integer, intent(out) :: ierr
integer :: fh

open(newunit=fh, file = path, iostat = ierr )
if (ierr /=0 ) return
inquire( unit=fh, size = sz, iostat = ierr )
close(fh)

end subroutine local_getsize_routine

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-706690003,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YR67MYLDQ5K5EJFU763SKGIZXANCNFSM4O45YWQA
.

Well, I will implement the workaround with comments to indicate the reason
for this. There is definitely something fishy wrt inquire(size).

Op zo 11 okt. 2020 om 17:20 schreef Martin Diehl notifications@github.com:

could be also related to
https://community.intel.com/t5/Intel-Fortran-Compiler/Reading-file-of-length-zero/m-p/1185659

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/fortran-lang/stdlib/issues/220#issuecomment-706720676,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAN6YRYSPV2VOPTUCLG5QOLSKHEMTANCNFSM4O45YWQA
.

Have an old file talking about six methods to do this depending on the vintage of the compiler. Was going to send it but I think most methods were mentioned (INQUIRE, ISO_C_BINDING, output of external command, open in append mode as a stream and get position-1, .... I have notes in there about a lot of compilers or systems not supporting multiple simultaneous opens on the file so I think your test should already have the file open to test for that; although the notes look like most of the notes are from 2008.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

certik picture certik  Â·  5Comments

masuday picture masuday  Â·  5Comments

certik picture certik  Â·  8Comments

certik picture certik  Â·  7Comments

leonfoks picture leonfoks  Â·  9Comments