ensure_directory_exists Subroutine

public subroutine ensure_directory_exists(path, ierr)

Create path via libc mkdir(2) if it does not already exist (single path component — not a recursive mkdir -p; a missing grandparent still fails, loudly, at the inquire re-check below). Exists to close the headline P7 crash: &ocean_diag_nml/ &output_nml default output_dir = "./output" (rdb_config.F90:2316), so a first-time create() against a fresh checkout with no ./output/ directory would otherwise reach nc_create_file -> nf90_create -> ENOENT -> error stop, killing the whole host process.

Never error stops itself, present ierr or not — the caller decides how to fail (via its OWN nc_create_file(..., ierr=) call on the resulting still-missing directory, or by checking this routine’s ierr directly). ierr is a plain 0-ok/ non-zero-failed flag (not an nf90_* status), because mkdir is not a NetCDF call and has no nc_check counterpart.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: path
integer, intent(out), optional :: ierr

Non-zero iff path still does not exist after the mkdir attempt. Absent is legal — the routine just does its best and lets the caller’s own I/O call fail loud.


Calls

proc~~ensure_directory_exists~~CallsGraph proc~ensure_directory_exists ensure_directory_exists none~c_mkdir c_mkdir proc~ensure_directory_exists->none~c_mkdir proc~path_to_c_string path_to_c_string proc~ensure_directory_exists->proc~path_to_c_string to_string to_string proc~ensure_directory_exists->to_string warning warning proc~ensure_directory_exists->warning

Called by

proc~~ensure_directory_exists~~CalledByGraph proc~ensure_directory_exists ensure_directory_exists proc~engine_configure_diag engine_configure_diag proc~engine_configure_diag->proc~ensure_directory_exists proc~engine_setup engine_setup proc~engine_setup->proc~engine_configure_diag proc~complete_ocean_create complete_ocean_create proc~complete_ocean_create->proc~engine_setup proc~driver_run_ocean driver_run_ocean proc~driver_run_ocean->proc~engine_setup proc~driver_validate driver_validate proc~driver_validate->proc~engine_setup proc~driver_run driver_run proc~driver_run->proc~driver_run_ocean proc~rdb_ocean_create_finalize rdb_ocean_create_finalize proc~rdb_ocean_create_finalize->proc~complete_ocean_create proc~rdb_ocean_create_from_string rdb_ocean_create_from_string proc~rdb_ocean_create_from_string->proc~complete_ocean_create

Variables

Type Visibility Attributes Name Initial
character(kind=c_char, len=1), private, allocatable, target :: c_path(:)
logical, private :: exists
integer(kind=c_int), private :: rc

Interfaces

interface

  • function c_mkdir(dirpath, mode) result(r) bind(C, name="mkdir"))

    Arguments

    Type IntentOptional Attributes Name
    type(c_ptr), intent(in), value :: dirpath
    integer(kind=c_int), intent(in), value :: mode

    Return Value integer(kind=c_int)


Source Code

   subroutine ensure_directory_exists(path, ierr)
      !! Create `path` via libc `mkdir(2)` if it does not already exist
      !! (single path component — not a recursive `mkdir -p`; a missing
      !! grandparent still fails, loudly, at the `inquire` re-check
      !! below). Exists to close the headline P7 crash: `&ocean_diag_nml`/
      !! `&output_nml` default `output_dir = "./output"`
      !! (`rdb_config.F90:2316`), so a first-time `create()` against a
      !! fresh checkout with no `./output/` directory would otherwise
      !! reach `nc_create_file` -> `nf90_create` -> ENOENT ->
      !! `error stop`, killing the whole host process.
      !!
      !! Never `error stop`s itself, present `ierr` or not — the caller
      !! decides how to fail (via its OWN `nc_create_file(..., ierr=)`
      !! call on the resulting still-missing directory, or by checking
      !! this routine's `ierr` directly). `ierr` is a plain 0-ok/
      !! non-zero-failed flag (not an `nf90_*` status), because `mkdir`
      !! is not a NetCDF call and has no `nc_check` counterpart.
      character(len=*), intent(in) :: path
      integer, intent(out), optional :: ierr
         !! Non-zero iff `path` still does not exist after the `mkdir`
         !! attempt. Absent is legal — the routine just does its best and
         !! lets the caller's own I/O call fail loud.

      logical :: exists
      integer(c_int) :: rc
      character(kind=c_char), allocatable, target :: c_path(:)
      interface
         function c_mkdir(dirpath, mode) bind(C, name="mkdir") result(r)
            import :: c_ptr, c_int
            implicit none
            type(c_ptr), value, intent(in) :: dirpath
            integer(c_int), value, intent(in) :: mode
            integer(c_int) :: r
         end function c_mkdir
      end interface

      if (present(ierr)) ierr = 0
      if (len_trim(path) == 0) return

      inquire (file=trim(path), exist=exists)
      if (exists) return

      c_path = path_to_c_string(trim(path))
      rc = c_mkdir(c_loc(c_path), int(o'755', c_int))
      if (rc /= 0_c_int) then
         call logger%warning("ensure_directory_exists: mkdir('"//trim(path)// &
                             "') returned "//to_string(int(rc))// &
                             " -- the subsequent NetCDF create/open will "// &
                             "report the exact failure if the directory "// &
                             "is still missing")
      end if

      inquire (file=trim(path), exist=exists)
      if (.not. exists) then
         if (present(ierr)) ierr = -1
      end if

   end subroutine ensure_directory_exists