LCOV - code coverage report
Current view: top level - src/common - cp_files.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 79.1 % 234 185
Test Date: 2026-09-24 01:27:39 Functions: 91.7 % 12 11

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utility routines to open and close files. Tracking of preconnections.
      10              : !> \par History
      11              : !>      - Creation CP2K_WORKSHOP 1.0 TEAM
      12              : !>      - Revised (18.02.2011,MK)
      13              : !>      - Enhanced error checking (22.02.2011,MK)
      14              : !> \author Matthias Krack (MK)
      15              : ! **************************************************************************************************
      16              : MODULE cp_files
      17              :    USE ISO_C_BINDING,                   ONLY: C_CHAR,&
      18              :                                               C_F_POINTER,&
      19              :                                               C_NULL_CHAR,&
      20              :                                               C_PTR
      21              :    USE kinds,                           ONLY: default_path_length
      22              :    USE machine,                         ONLY: default_input_unit,&
      23              :                                               default_output_unit,&
      24              :                                               m_getcwd
      25              : #include "../base/base_uses.f90"
      26              : 
      27              :    IMPLICIT NONE
      28              : 
      29              :    PRIVATE
      30              : 
      31              :    PUBLIC :: close_file, &
      32              :              init_preconnection_list, &
      33              :              open_file, &
      34              :              get_unit_number, &
      35              :              file_exists, &
      36              :              get_data_dir, &
      37              :              discover_file
      38              : 
      39              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_files'
      40              : 
      41              :    INTEGER, PARAMETER :: max_preconnections = 10, &
      42              :                          max_unit_number = 999
      43              : 
      44              :    TYPE preconnection_type
      45              :       PRIVATE
      46              :       CHARACTER(LEN=default_path_length) :: file_name = ""
      47              :       INTEGER                            :: unit_number = -1
      48              :    END TYPE preconnection_type
      49              : 
      50              :    TYPE(preconnection_type), DIMENSION(max_preconnections) :: preconnected
      51              : 
      52              : CONTAINS
      53              : 
      54              : ! **************************************************************************************************
      55              : !> \brief Add an entry to the list of preconnected units
      56              : !> \param file_name ...
      57              : !> \param unit_number ...
      58              : !> \par History
      59              : !>      - Creation (22.02.2011,MK)
      60              : !> \author Matthias Krack (MK)
      61              : ! **************************************************************************************************
      62          755 :    SUBROUTINE assign_preconnection(file_name, unit_number)
      63              : 
      64              :       CHARACTER(LEN=*), INTENT(IN)                       :: file_name
      65              :       INTEGER, INTENT(IN)                                :: unit_number
      66              : 
      67              :       INTEGER                                            :: ic, islot, nc
      68              : 
      69          755 :       IF ((unit_number < 1) .OR. (unit_number > max_unit_number)) THEN
      70            0 :          CPABORT("An invalid logical unit number was specified.")
      71              :       END IF
      72              : 
      73          755 :       IF (LEN_TRIM(file_name) == 0) THEN
      74            0 :          CPABORT("No valid file name was specified.")
      75              :       END IF
      76              : 
      77              :       nc = SIZE(preconnected)
      78              : 
      79              :       ! Check if a preconnection already exists
      80         3442 :       DO ic = 1, nc
      81         3442 :          IF (TRIM(preconnected(ic)%file_name) == TRIM(file_name)) THEN
      82              :             ! Return if the entry already exists
      83          728 :             IF (preconnected(ic)%unit_number == unit_number) THEN
      84              :                RETURN
      85              :             ELSE
      86            0 :                CALL print_preconnection_list()
      87              :                CALL cp_abort(__LOCATION__, &
      88              :                              "Attempt to connect the already connected file <"// &
      89            0 :                              TRIM(file_name)//"> to another unit.")
      90              :             END IF
      91              :          END IF
      92              :       END DO
      93              : 
      94              :       ! Search for an unused entry
      95          163 :       islot = -1
      96          163 :       DO ic = 1, nc
      97          163 :          IF (preconnected(ic)%unit_number == -1) THEN
      98              :             islot = ic
      99              :             EXIT
     100              :          END IF
     101              :       END DO
     102              : 
     103           27 :       IF (islot == -1) THEN
     104            0 :          CALL print_preconnection_list()
     105            0 :          CPABORT("No free slot found in the list of preconnected units.")
     106              :       END IF
     107              : 
     108           27 :       preconnected(islot)%file_name = TRIM(file_name)
     109           27 :       preconnected(islot)%unit_number = unit_number
     110              : 
     111          755 :    END SUBROUTINE assign_preconnection
     112              : 
     113              : ! **************************************************************************************************
     114              : !> \brief Close an open file given by its logical unit number.
     115              : !>        Optionally, keep the file and unit preconnected.
     116              : !> \param unit_number ...
     117              : !> \param file_status ...
     118              : !> \param keep_preconnection ...
     119              : !> \author Matthias Krack (MK)
     120              : ! **************************************************************************************************
     121       138617 :    SUBROUTINE close_file(unit_number, file_status, keep_preconnection)
     122              : 
     123              :       INTEGER, INTENT(IN)                                :: unit_number
     124              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: file_status
     125              :       LOGICAL, INTENT(IN), OPTIONAL                      :: keep_preconnection
     126              : 
     127              :       CHARACTER(LEN=2*default_path_length)               :: message
     128              :       CHARACTER(LEN=6)                                   :: status_string
     129              :       CHARACTER(LEN=default_path_length)                 :: file_name
     130              :       INTEGER                                            :: istat
     131              :       LOGICAL                                            :: exists, is_named, is_open, &
     132              :                                                             keep_file_connection
     133              : 
     134       138617 :       keep_file_connection = .FALSE.
     135          755 :       IF (PRESENT(keep_preconnection)) keep_file_connection = keep_preconnection
     136              : 
     137       138617 :       INQUIRE (UNIT=unit_number, EXIST=exists, OPENED=is_open, IOSTAT=istat)
     138              : 
     139       138617 :       IF (istat /= 0) THEN
     140              :          WRITE (UNIT=message, FMT="(A,I0,A,I0,A)") &
     141            0 :             "An error occurred inquiring the unit with the number ", unit_number, &
     142            0 :             " (IOSTAT = ", istat, ")"
     143            0 :          CPABORT(TRIM(message))
     144       138617 :       ELSE IF (.NOT. exists) THEN
     145              :          WRITE (UNIT=message, FMT="(A,I0,A)") &
     146            0 :             "The specified unit number ", unit_number, &
     147            0 :             " cannot be closed, because it does not exist."
     148            0 :          CPABORT(TRIM(message))
     149              :       END IF
     150              : 
     151              :       ! Close the specified file
     152              : 
     153       138617 :       IF (is_open) THEN
     154              :          ! Refuse to close any preconnected system unit
     155       138614 :          IF (unit_number == default_input_unit) THEN
     156              :             WRITE (UNIT=message, FMT="(A,I0)") &
     157            0 :                "Attempt to close the default input unit number ", unit_number
     158            0 :             CPABORT(TRIM(message))
     159              :          END IF
     160       138614 :          IF (unit_number == default_output_unit) THEN
     161              :             WRITE (UNIT=message, FMT="(A,I0)") &
     162            0 :                "Attempt to close the default output unit number ", unit_number
     163            0 :             CPABORT(TRIM(message))
     164              :          END IF
     165              :          ! Anonymous scratch files cannot be retained or preconnected by name.
     166       138614 :          INQUIRE (UNIT=unit_number, NAMED=is_named, IOSTAT=istat)
     167       138614 :          CPASSERT(istat == 0)
     168       138614 :          IF (.NOT. is_named .AND. keep_file_connection) THEN
     169            0 :             CPABORT("Cannot keep a preconnection for an anonymous scratch file")
     170              :          END IF
     171              :          ! Define status after closing the file
     172       138614 :          IF (PRESENT(file_status)) THEN
     173        89904 :             status_string = TRIM(file_status)
     174        48710 :          ELSE IF (.NOT. is_named) THEN
     175            4 :             status_string = "DELETE"
     176              :          ELSE
     177        48706 :             status_string = "KEEP"
     178              :          END IF
     179              :          ! Optionally, keep this unit preconnected
     180       138614 :          IF (is_named) THEN
     181       138610 :             INQUIRE (UNIT=unit_number, NAME=file_name, IOSTAT=istat)
     182       138610 :             IF (istat /= 0) THEN
     183              :                WRITE (UNIT=message, FMT="(A,I0,A,I0,A)") &
     184            0 :                   "An error occurred inquiring the unit with the number ", unit_number, &
     185            0 :                   " (IOSTAT = ", istat, ")."
     186            0 :                CPABORT(TRIM(message))
     187              :             END IF
     188              :          END IF
     189              :          ! Manage preconnections
     190       138614 :          IF (keep_file_connection) THEN
     191          755 :             CALL assign_preconnection(file_name, unit_number)
     192              :          ELSE
     193       137859 :             IF (is_named) CALL delete_preconnection(file_name, unit_number)
     194       137859 :             CLOSE (UNIT=unit_number, IOSTAT=istat, STATUS=TRIM(status_string))
     195       137859 :             IF (istat /= 0) THEN
     196              :                WRITE (UNIT=message, FMT="(A,I0,A,I0,A)") &
     197            0 :                   "An error occurred closing the file with the logical unit number ", &
     198            0 :                   unit_number, " (IOSTAT = ", istat, ")."
     199            0 :                CPABORT(TRIM(message))
     200              :             END IF
     201              :          END IF
     202              :       END IF
     203              : 
     204       138617 :    END SUBROUTINE close_file
     205              : 
     206              : ! **************************************************************************************************
     207              : !> \brief Remove an entry from the list of preconnected units
     208              : !> \param file_name ...
     209              : !> \param unit_number ...
     210              : !> \par History
     211              : !>      - Creation (22.02.2011,MK)
     212              : !> \author Matthias Krack (MK)
     213              : ! **************************************************************************************************
     214       137855 :    SUBROUTINE delete_preconnection(file_name, unit_number)
     215              : 
     216              :       CHARACTER(LEN=*), INTENT(IN)                       :: file_name
     217              :       INTEGER                                            :: unit_number
     218              : 
     219              :       INTEGER                                            :: ic, nc
     220              : 
     221       137855 :       nc = SIZE(preconnected)
     222              : 
     223              :       ! Search for preconnection entry and delete it when found
     224      1516301 :       DO ic = 1, nc
     225      1516301 :          IF (TRIM(preconnected(ic)%file_name) == TRIM(file_name)) THEN
     226           22 :             IF (preconnected(ic)%unit_number == unit_number) THEN
     227           22 :                preconnected(ic)%file_name = ""
     228           22 :                preconnected(ic)%unit_number = -1
     229           22 :                EXIT
     230              :             ELSE
     231            0 :                CALL print_preconnection_list()
     232              :                CALL cp_abort(__LOCATION__, &
     233              :                              "Attempt to disconnect the file <"// &
     234              :                              TRIM(file_name)// &
     235            0 :                              "> from an unlisted unit.")
     236              :             END IF
     237              :          END IF
     238              :       END DO
     239              : 
     240       137855 :    END SUBROUTINE delete_preconnection
     241              : 
     242              : ! **************************************************************************************************
     243              : !> \brief Returns the first logical unit that is not preconnected
     244              : !> \param file_name ...
     245              : !> \return ...
     246              : !> \author Matthias Krack (MK)
     247              : !> \note
     248              : !>       -1 if no free unit exists
     249              : ! **************************************************************************************************
     250       142361 :    FUNCTION get_unit_number(file_name) RESULT(unit_number)
     251              : 
     252              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: file_name
     253              :       INTEGER                                            :: unit_number
     254              : 
     255              :       INTEGER                                            :: ic, istat, nc
     256              :       LOGICAL                                            :: exists, is_open
     257              : 
     258       142361 :       IF (PRESENT(file_name)) THEN
     259              :          nc = SIZE(preconnected)
     260              :          ! Check for preconnected units
     261      1221933 :          DO ic = 3, nc ! Exclude the preconnected system units (< 3)
     262      1221933 :             IF (TRIM(preconnected(ic)%file_name) == TRIM(file_name)) THEN
     263           18 :                unit_number = preconnected(ic)%unit_number
     264           18 :                RETURN
     265              :             END IF
     266              :          END DO
     267              :       END IF
     268              : 
     269              :       ! Get a new unit number
     270       708357 :       DO unit_number = 1, max_unit_number
     271      7096309 :          IF (ANY(unit_number == preconnected(:)%unit_number)) CYCLE
     272       630143 :          INQUIRE (UNIT=unit_number, EXIST=exists, OPENED=is_open, IOSTAT=istat)
     273       630143 :          IF (exists .AND. (.NOT. is_open) .AND. (istat == 0)) RETURN
     274              :       END DO
     275              : 
     276       142361 :       unit_number = -1
     277              : 
     278              :    END FUNCTION get_unit_number
     279              : 
     280              : ! **************************************************************************************************
     281              : !> \brief Allocate and initialise the list of preconnected units
     282              : !> \par History
     283              : !>      - Creation (22.02.2011,MK)
     284              : !> \author Matthias Krack (MK)
     285              : ! **************************************************************************************************
     286         1382 :    SUBROUTINE init_preconnection_list()
     287              : 
     288              :       INTEGER                                            :: ic, nc
     289              : 
     290         1382 :       nc = SIZE(preconnected)
     291              : 
     292        15202 :       DO ic = 1, nc
     293        13820 :          preconnected(ic)%file_name = ""
     294        15202 :          preconnected(ic)%unit_number = -1
     295              :       END DO
     296              : 
     297              :       ! Define reserved unit numbers
     298         1382 :       preconnected(1)%file_name = "stdin"
     299         1382 :       preconnected(1)%unit_number = default_input_unit
     300         1382 :       preconnected(2)%file_name = "stdout"
     301         1382 :       preconnected(2)%unit_number = default_output_unit
     302              : 
     303         1382 :    END SUBROUTINE init_preconnection_list
     304              : 
     305              : ! **************************************************************************************************
     306              : !> \brief Opens the requested file using a free unit number
     307              : !> \param file_name File name; must be empty for an anonymous SCRATCH file
     308              : !> \param file_status Fortran file status, including SCRATCH for temporary files
     309              : !> \param file_form ...
     310              : !> \param file_action ...
     311              : !> \param file_position ...
     312              : !> \param file_pad ...
     313              : !> \param unit_number ...
     314              : !> \param debug ...
     315              : !> \param skip_get_unit_number ...
     316              : !> \param file_access file access mode
     317              : !> \author Matthias Krack (MK)
     318              : ! **************************************************************************************************
     319       141165 :    SUBROUTINE open_file(file_name, file_status, file_form, file_action, &
     320              :                         file_position, file_pad, unit_number, debug, &
     321              :                         skip_get_unit_number, file_access)
     322              : 
     323              :       CHARACTER(LEN=*), INTENT(IN)                       :: file_name
     324              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: file_status, file_form, file_action, &
     325              :                                                             file_position, file_pad
     326              :       INTEGER, INTENT(INOUT)                             :: unit_number
     327              :       INTEGER, INTENT(IN), OPTIONAL                      :: debug
     328              :       LOGICAL, INTENT(IN), OPTIONAL                      :: skip_get_unit_number
     329              :       CHARACTER(LEN=*), INTENT(IN), OPTIONAL             :: file_access
     330              : 
     331              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'open_file'
     332              : 
     333              :       CHARACTER(LEN=11) :: access_string, action_string, current_action, current_form, &
     334              :          form_string, pad_string, position_string, status_string
     335              :       CHARACTER(LEN=2*default_path_length)               :: message
     336              :       CHARACTER(LEN=default_path_length)                 :: cwd, iomsgstr, real_file_name
     337              :       INTEGER                                            :: debug_unit, istat
     338              :       LOGICAL                                            :: exists, get_a_new_unit, is_open
     339              : 
     340       141165 :       IF (PRESENT(file_access)) THEN
     341           25 :          access_string = TRIM(file_access)
     342              :       ELSE
     343       141140 :          access_string = "SEQUENTIAL"
     344              :       END IF
     345              : 
     346       141165 :       IF (PRESENT(file_status)) THEN
     347       107517 :          status_string = TRIM(file_status)
     348              :       ELSE
     349        33648 :          status_string = "OLD"
     350              :       END IF
     351              : 
     352       141165 :       IF (PRESENT(file_form)) THEN
     353        98574 :          form_string = TRIM(file_form)
     354              :       ELSE
     355        42591 :          form_string = "FORMATTED"
     356              :       END IF
     357              : 
     358       141165 :       IF (PRESENT(file_pad)) THEN
     359            2 :          pad_string = file_pad
     360            2 :          IF (form_string == "UNFORMATTED") THEN
     361              :             WRITE (UNIT=message, FMT="(A)") &
     362            0 :                "The PAD specifier is not allowed for an UNFORMATTED file."
     363            0 :             CPABORT(TRIM(message))
     364              :          END IF
     365              :       ELSE
     366       141163 :          pad_string = "YES"
     367              :       END IF
     368              : 
     369       141165 :       IF (PRESENT(file_action)) THEN
     370       107517 :          action_string = TRIM(file_action)
     371              :       ELSE
     372        33648 :          action_string = "READ"
     373              :       END IF
     374              : 
     375       141165 :       IF (PRESENT(file_position)) THEN
     376       101450 :          position_string = TRIM(file_position)
     377              :       ELSE
     378        39715 :          position_string = "REWIND"
     379              :       END IF
     380              : 
     381       141165 :       IF (PRESENT(debug)) THEN
     382          138 :          debug_unit = debug
     383              :       ELSE
     384       141027 :          debug_unit = 0 ! use default_output_unit for debugging
     385              :       END IF
     386              : 
     387       141165 :       IF (status_string == "SCRATCH") THEN
     388            4 :          CPASSERT(LEN_TRIM(file_name) == 0)
     389            4 :          get_a_new_unit = .TRUE.
     390            4 :          IF (PRESENT(skip_get_unit_number)) get_a_new_unit = .NOT. skip_get_unit_number
     391            4 :          IF (get_a_new_unit) unit_number = get_unit_number()
     392            4 :          CPASSERT(unit_number > 0)
     393            4 :          IF (form_string == "FORMATTED") THEN
     394              :             OPEN (UNIT=unit_number, STATUS="SCRATCH", ACCESS=access_string, FORM=form_string, &
     395            2 :                   POSITION=position_string, ACTION=action_string, PAD=pad_string, IOMSG=iomsgstr, IOSTAT=istat)
     396              :          ELSE
     397              :             OPEN (UNIT=unit_number, STATUS="SCRATCH", ACCESS=access_string, FORM=form_string, &
     398            2 :                   POSITION=position_string, ACTION=action_string, IOMSG=iomsgstr, IOSTAT=istat)
     399              :          END IF
     400            4 :          IF (istat /= 0) THEN
     401            0 :             CALL cp_abort(__LOCATION__, "Error opening an anonymous scratch file: "//TRIM(iomsgstr))
     402              :          END IF
     403            4 :          RETURN
     404              :       END IF
     405              : 
     406       141161 :       IF (file_name(1:1) == " ") THEN
     407              :          WRITE (UNIT=message, FMT="(A)") &
     408            0 :             "The file name <"//TRIM(file_name)//"> has leading blanks."
     409            0 :          CPABORT(TRIM(message))
     410              :       END IF
     411              : 
     412       141161 :       IF (status_string == "OLD") THEN
     413        41760 :          real_file_name = discover_file(file_name)
     414              :       ELSE
     415              :          ! Strip leading and trailing blanks from file name
     416        99401 :          real_file_name = TRIM(ADJUSTL(file_name))
     417        99401 :          IF (LEN_TRIM(real_file_name) == 0) THEN
     418            0 :             CPABORT("A file name length of zero for a new file is invalid.")
     419              :          END IF
     420              :       END IF
     421              : 
     422              :       ! Check the specified input file name
     423       141161 :       INQUIRE (FILE=TRIM(real_file_name), EXIST=exists, OPENED=is_open, IOSTAT=istat)
     424              : 
     425       141161 :       IF (istat /= 0) THEN
     426              :          WRITE (UNIT=message, FMT="(A,I0,A)") &
     427              :             "An error occurred inquiring the file <"//TRIM(real_file_name)// &
     428            0 :             "> (IOSTAT = ", istat, ")"
     429            0 :          CPABORT(TRIM(message))
     430       141161 :       ELSE IF (status_string == "OLD") THEN
     431        41760 :          IF (.NOT. exists) THEN
     432              :             WRITE (UNIT=message, FMT="(A)") &
     433              :                "The specified OLD file <"//TRIM(real_file_name)// &
     434              :                "> cannot be opened. It does not exist. "// &
     435            0 :                "Data directory path: "//TRIM(get_data_dir())
     436            0 :             CPABORT(TRIM(message))
     437              :          END IF
     438              :       END IF
     439              : 
     440              :       ! Open the specified input file
     441       141161 :       IF (is_open) THEN
     442              :          INQUIRE (FILE=TRIM(real_file_name), NUMBER=unit_number, &
     443         2581 :                   ACTION=current_action, FORM=current_form)
     444         2581 :          IF (TRIM(position_string) == "REWIND") REWIND (UNIT=unit_number)
     445         2581 :          IF (TRIM(status_string) == "NEW") THEN
     446              :             CALL cp_abort(__LOCATION__, &
     447              :                           "Attempt to re-open the existing OLD file <"// &
     448            0 :                           TRIM(real_file_name)//"> with status attribute NEW.")
     449              :          END IF
     450         2581 :          IF (TRIM(current_form) /= TRIM(form_string)) THEN
     451              :             CALL cp_abort(__LOCATION__, &
     452              :                           "Attempt to re-open the existing "// &
     453              :                           TRIM(current_form)//" file <"//TRIM(real_file_name)// &
     454            0 :                           "> as "//TRIM(form_string)//" file.")
     455              :          END IF
     456         2581 :          IF (TRIM(current_action) /= TRIM(action_string)) THEN
     457              :             CALL cp_abort(__LOCATION__, &
     458              :                           "Attempt to re-open the existing file <"// &
     459              :                           TRIM(real_file_name)//"> with the modified ACTION attribute "// &
     460              :                           TRIM(action_string)//". The current ACTION attribute is "// &
     461            0 :                           TRIM(current_action)//".")
     462              :          END IF
     463              :       ELSE
     464              :          ! Find an unused unit number
     465       138580 :          get_a_new_unit = .TRUE.
     466       138580 :          IF (PRESENT(skip_get_unit_number)) THEN
     467         2801 :             IF (skip_get_unit_number) get_a_new_unit = .FALSE.
     468              :          END IF
     469       135779 :          IF (get_a_new_unit) unit_number = get_unit_number(TRIM(real_file_name))
     470       138580 :          IF (unit_number < 1) THEN
     471              :             WRITE (UNIT=message, FMT="(A)") &
     472              :                "Cannot open the file <"//TRIM(real_file_name)// &
     473            0 :                ">, because no unused logical unit number could be obtained."
     474            0 :             CPABORT(TRIM(message))
     475              :          END IF
     476       138580 :          IF (TRIM(form_string) == "FORMATTED") THEN
     477              :             OPEN (UNIT=unit_number, &
     478              :                   FILE=TRIM(real_file_name), &
     479              :                   STATUS=TRIM(status_string), &
     480              :                   ACCESS=TRIM(access_string), &
     481              :                   FORM=TRIM(form_string), &
     482              :                   POSITION=TRIM(position_string), &
     483              :                   ACTION=TRIM(action_string), &
     484              :                   PAD=TRIM(pad_string), &
     485              :                   IOMSG=iomsgstr, &
     486       116329 :                   IOSTAT=istat)
     487              :          ELSE
     488              :             OPEN (UNIT=unit_number, &
     489              :                   FILE=TRIM(real_file_name), &
     490              :                   STATUS=TRIM(status_string), &
     491              :                   ACCESS=TRIM(access_string), &
     492              :                   FORM=TRIM(form_string), &
     493              :                   POSITION=TRIM(position_string), &
     494              :                   ACTION=TRIM(action_string), &
     495              :                   IOMSG=iomsgstr, &
     496        22251 :                   IOSTAT=istat)
     497              :          END IF
     498       138580 :          IF (istat /= 0) THEN
     499            0 :             CALL m_getcwd(cwd)
     500              :             WRITE (UNIT=message, FMT="(A,I0,A,I0,A)") &
     501              :                "An error occurred opening the file '"//TRIM(real_file_name)// &
     502            0 :                "' (UNIT = ", unit_number, ", IOSTAT = ", istat, "). "//TRIM(iomsgstr)//". "// &
     503            0 :                "Current working directory: "//TRIM(cwd)
     504              : 
     505            0 :             CPABORT(TRIM(message))
     506              :          END IF
     507              :       END IF
     508              : 
     509       141161 :       IF (debug_unit > 0) THEN
     510              :          INQUIRE (FILE=TRIM(real_file_name), OPENED=is_open, NUMBER=unit_number, &
     511              :                   POSITION=position_string, NAME=message, ACCESS=access_string, &
     512          138 :                   FORM=form_string, ACTION=action_string)
     513          138 :          WRITE (UNIT=debug_unit, FMT="(T2,A)") "BEGIN DEBUG "//TRIM(routineN)
     514          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A,I0)") "NUMBER  : ", unit_number
     515          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A,L1)") "OPENED  : ", is_open
     516          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A)") "NAME    : "//TRIM(message)
     517          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A)") "POSITION: "//TRIM(position_string)
     518          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A)") "ACCESS  : "//TRIM(access_string)
     519          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A)") "FORM    : "//TRIM(form_string)
     520          138 :          WRITE (UNIT=debug_unit, FMT="(T3,A)") "ACTION  : "//TRIM(action_string)
     521          138 :          WRITE (UNIT=debug_unit, FMT="(T2,A)") "END DEBUG "//TRIM(routineN)
     522          138 :          CALL print_preconnection_list(debug_unit)
     523              :       END IF
     524              : 
     525       141165 :    END SUBROUTINE open_file
     526              : 
     527              : ! **************************************************************************************************
     528              : !> \brief Checks if file exists, considering also the file discovery mechanism.
     529              : !> \param file_name ...
     530              : !> \return ...
     531              : !> \author Ole Schuett
     532              : ! **************************************************************************************************
     533          713 :    FUNCTION file_exists(file_name) RESULT(exist)
     534              :       CHARACTER(LEN=*), INTENT(IN)                       :: file_name
     535              :       LOGICAL                                            :: exist
     536              : 
     537              :       CHARACTER(LEN=default_path_length)                 :: real_file_name
     538              : 
     539          713 :       real_file_name = discover_file(file_name)
     540          713 :       INQUIRE (FILE=TRIM(real_file_name), EXIST=exist)
     541              : 
     542          713 :    END FUNCTION file_exists
     543              : 
     544              : ! **************************************************************************************************
     545              : !> \brief Checks various locations for a file name.
     546              : !> \param file_name ...
     547              : !> \return ...
     548              : !> \author Ole Schuett
     549              : ! **************************************************************************************************
     550        42498 :    FUNCTION discover_file(file_name) RESULT(real_file_name)
     551              :       CHARACTER(LEN=*), INTENT(IN)                       :: file_name
     552              :       CHARACTER(LEN=default_path_length)                 :: real_file_name
     553              : 
     554              :       CHARACTER(LEN=default_path_length)                 :: candidate, data_dir
     555              :       INTEGER                                            :: stat
     556              :       LOGICAL                                            :: exists
     557              : 
     558              :       ! Strip leading and trailing blanks from file name
     559        42498 :       real_file_name = TRIM(ADJUSTL(file_name))
     560              : 
     561        42498 :       IF (LEN_TRIM(real_file_name) == 0) THEN
     562            0 :          CPABORT("A file name length of zero for an existing file is invalid.")
     563              :       END IF
     564              : 
     565              :       ! First try file name directly
     566        42498 :       INQUIRE (FILE=TRIM(real_file_name), EXIST=exists, IOSTAT=stat)
     567        58890 :       IF (stat == 0 .AND. exists) RETURN
     568              : 
     569              :       ! Then try the data directory
     570        16483 :       data_dir = get_data_dir()
     571        16483 :       IF (LEN_TRIM(data_dir) > 0) THEN
     572        16483 :          candidate = join_paths(data_dir, real_file_name)
     573        16483 :          INQUIRE (FILE=TRIM(candidate), EXIST=exists, IOSTAT=stat)
     574        16483 :          IF (stat == 0 .AND. exists) THEN
     575        16392 :             real_file_name = candidate
     576        16392 :             RETURN
     577              :          END IF
     578              :       END IF
     579              : 
     580        42498 :    END FUNCTION discover_file
     581              : 
     582              : ! **************************************************************************************************
     583              : !> \brief Returns path of data directory if set, otherwise an empty string
     584              : !> \return ...
     585              : !> \author Ole Schuett
     586              : ! **************************************************************************************************
     587        22381 :    FUNCTION get_data_dir() RESULT(res)
     588              :       CHARACTER(len=default_path_length)                 :: res
     589              : 
     590              :       CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(:), &
     591        22381 :          POINTER                                         :: path_f
     592              :       INTEGER                                            :: i
     593              :       TYPE(C_PTR)                                        :: path_c
     594              :       INTERFACE
     595              :          FUNCTION get_data_dir_c() BIND(C, name="get_data_dir")
     596              :             IMPORT :: C_PTR
     597              :             TYPE(C_PTR)                               :: get_data_dir_c
     598              :          END FUNCTION get_data_dir_c
     599              :       END INTERFACE
     600              : 
     601        22381 :       path_c = get_data_dir_c()
     602        44762 :       CALL C_F_POINTER(path_c, path_f, shape=[default_path_length])
     603              : 
     604        22381 :       res = ""
     605       335715 :       DO i = 1, default_path_length
     606       335715 :          IF (path_f(i) == C_NULL_CHAR) RETURN
     607       313334 :          res(i:i) = path_f(i)
     608              :       END DO
     609              : 
     610            0 :       CPABORT("CP2K_DATA_DIR path is too long")
     611              : 
     612        22381 :    END FUNCTION get_data_dir
     613              : 
     614              : ! **************************************************************************************************
     615              : !> \brief Joins two file-paths, inserting '/' as needed.
     616              : !> \param path1 ...
     617              : !> \param path2 ...
     618              : !> \return ...
     619              : !> \author Ole Schuett
     620              : ! **************************************************************************************************
     621        16483 :    FUNCTION join_paths(path1, path2) RESULT(joined_path)
     622              :       CHARACTER(LEN=*), INTENT(IN)                       :: path1, path2
     623              :       CHARACTER(LEN=default_path_length)                 :: joined_path
     624              : 
     625              :       INTEGER                                            :: n
     626              : 
     627        16483 :       n = LEN_TRIM(path1)
     628        16483 :       IF (path2(1:1) == '/') THEN
     629            0 :          joined_path = path2
     630        16483 :       ELSE IF (n == 0 .OR. path1(n:n) == '/') THEN
     631            0 :          joined_path = TRIM(path1)//path2
     632              :       ELSE
     633        16483 :          joined_path = TRIM(path1)//'/'//path2
     634              :       END IF
     635        16483 :    END FUNCTION join_paths
     636              : 
     637              : ! **************************************************************************************************
     638              : !> \brief Print the list of preconnected units
     639              : !> \param output_unit which unit to print to (optional)
     640              : !> \par History
     641              : !>      - Creation (22.02.2011,MK)
     642              : !> \author Matthias Krack (MK)
     643              : ! **************************************************************************************************
     644          138 :    SUBROUTINE print_preconnection_list(output_unit)
     645              :       INTEGER, INTENT(IN), OPTIONAL                      :: output_unit
     646              : 
     647              :       INTEGER                                            :: ic, nc, unit
     648              : 
     649              :       IF (PRESENT(output_unit)) THEN
     650          138 :          unit = output_unit
     651              :       ELSE
     652          138 :          unit = default_output_unit
     653              :       END IF
     654              : 
     655          138 :       nc = SIZE(preconnected)
     656              : 
     657          138 :       IF (output_unit > 0) THEN
     658              : 
     659              :          WRITE (UNIT=output_unit, FMT="(A,/,A)") &
     660          138 :             " LIST OF PRECONNECTED LOGICAL UNITS", &
     661          276 :             "  Slot   Unit number   File name"
     662         1518 :          DO ic = 1, nc
     663         1518 :             IF (preconnected(ic)%unit_number > 0) THEN
     664              :                WRITE (UNIT=output_unit, FMT="(I6,3X,I6,8X,A)") &
     665          871 :                   ic, preconnected(ic)%unit_number, &
     666         1742 :                   TRIM(preconnected(ic)%file_name)
     667              :             ELSE
     668              :                WRITE (UNIT=output_unit, FMT="(I6,17X,A)") &
     669          509 :                   ic, "UNUSED"
     670              :             END IF
     671              :          END DO
     672              :       END IF
     673          138 :    END SUBROUTINE print_preconnection_list
     674              : 
     675            0 : END MODULE cp_files
        

Generated by: LCOV version 2.0-1