diff --git a/.ci/bb/breeze-mpim/test.all.clang b/.ci/bb/breeze-mpim/test.all.clang
index 4396928c68c250a4e4ffec8438115620d321142d..6ca92e801cebe97dc9a3d07c0bdb1a3319c0bda5 100755
--- a/.ci/bb/breeze-mpim/test.all.clang
+++ b/.ci/bb/breeze-mpim/test.all.clang
@@ -9,15 +9,6 @@ top_srcdir=$(cd "${script_dir}/../../.."; pwd)
 . "${script_dir}/init.sh"
 init_clang
 
-# Check the formatting. Note that git-clang-format might keep redundant blank
-# lines. Therefore, we use clang-format:
-find src app interfaces tests examples \
-  \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' \) -a \
-  ! -path 'interfaces/python/cdi_wrapper.cpp' -a \
-  ! -path 'interfaces/ruby/cdi_wrapper.cpp' -a \
-  ! -path 'src/cdilib.c' \
-    | xargs -n 1 -P 8 clang-format --Werror --dry-run --verbose
-
 enable_maintainer_mode='no'
 if test ! -f "${top_srcdir}/configure"; then
   "${top_srcdir}/autogen.sh"
@@ -41,9 +32,9 @@ FCFLAGS='-g -O2 -no-pie' \
 MPI_LAUNCH="${MPI_LAUNCH}" \
 PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig"
 
-make -j8
+make
 
-make -j8 check || { cat tests/test-suite.log; exit 1; }
+make check || { cat tests/test-suite.log; exit 1; }
 
 check_all_tests_passed tests/test-suite.log
 
diff --git a/.ci/bb/breeze-mpim/test.all.nag b/.ci/bb/breeze-mpim/test.all.nag
index 68b2618a265fde6e05ad92cbe541814c297926c1..93c4c7939a0cd09b5e73a819384a6c40afa46d9f 100755
--- a/.ci/bb/breeze-mpim/test.all.nag
+++ b/.ci/bb/breeze-mpim/test.all.nag
@@ -16,7 +16,7 @@ test -f "${top_srcdir}/configure" || "${top_srcdir}/autogen.sh"
 # Use GCC from the path when compiling/linking Fortran code:
 export FCFLAGS="-g -O2 -Wc=$(which gcc)"
 
-make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS=" \
+make distcheck DISTCHECK_CONFIGURE_FLAGS=" \
 --disable-maintainer-mode \
 --enable-cf-interface \
 --enable-iso-c-interface \
@@ -30,7 +30,10 @@ FC='${MPIFC}' \
 FCFLAGS='${FCFLAGS}' \
 MPI_LAUNCH='${MPI_LAUNCH}' \
 PKG_CONFIG_PATH='${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig' \
-" | tee >(sed -n '/^Testsuite summary for cdi/,/^# ERROR:/p' > tests/test-suite.log)
+" | tee >(
+  sed 's/'$'\033''\[\([0-9]\{1,2\}\(;[0-9]\{1,2\}\)\?\)\?[mK]//g' |
+  sed -n '/^Testsuite summary for cdi/,/^# ERROR:/p' > tests/test-suite.log
+)
 
 check_all_tests_passed tests/test-suite.log
 
diff --git a/.ci/bb/breeze-mpim/test.all.nv b/.ci/bb/breeze-mpim/test.all.nv
index 4025ba7b5c2e8294d342e52efc9af9b294c1c34b..20c0f73671af09674fd00b922bfbddbd81442888 100755
--- a/.ci/bb/breeze-mpim/test.all.nv
+++ b/.ci/bb/breeze-mpim/test.all.nv
@@ -34,7 +34,7 @@ FC="${MPIFC}" \
 MPI_LAUNCH="${MPI_LAUNCH}" \
 PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig"
 
-make -j8
+make
 
 # Check that an executable is not overlinked to libscalesppmcore.so:
 tested_file='examples/pio/collectData.parallel'
@@ -55,7 +55,7 @@ if test -n "${invalid_needed}"; then
   exit 1
 fi
 
-make -j8 check || { cat tests/test-suite.log; exit 1; }
+make check || { cat tests/test-suite.log; exit 1; }
 
 check_all_tests_passed tests/test-suite.log
 
diff --git a/.ci/bb/breeze-mpim/test.ru-py.gcc b/.ci/bb/breeze-mpim/test.ru-py.gcc
index f514da1f6ca178cd888ce0a6194b04fcbf5c4bbb..c8a933cd2bd42913f61fa3611726b7d3b56d93ef 100755
--- a/.ci/bb/breeze-mpim/test.ru-py.gcc
+++ b/.ci/bb/breeze-mpim/test.ru-py.gcc
@@ -29,16 +29,16 @@ fi
 CC="${CC}" \
 CXX="${CXX}"
 
-make -j8
+make
 
-make -j8 check || { cat interfaces/test-suite.log tests/test-suite.log; exit 1; }
+make check || { cat interfaces/test-suite.log tests/test-suite.log; exit 1; }
 
 check_all_tests_passed interfaces/test-suite.log
 
 check_no_git_untracked
 
 # Check the installation:
-make -j8 install
+make install
 export RUBYLIB="$(find "${install_dir}" -name 'Cdi.so' -printf '%h'):${RUBYLIB-}"
 ruby ./interfaces/ruby/test.rb ./interfaces/testdata/mulval.grb
 ruby ./interfaces/ruby/test.rb ./interfaces/testdata/mulval.nc
@@ -47,7 +47,7 @@ python ./interfaces/python/test.py ./interfaces/testdata/mulval.grb
 python ./interfaces/python/test.py ./interfaces/testdata/mulval.nc
 
 # Check the uninstallation:
-make -j8 uninstall
+make uninstall
 remaining_files=$(find "${install_dir}" -type f) || {
   echo "ERROR: failed to get the list of files in the installation prefix '${install_dir}'" >&2
   exit 1
diff --git a/.ci/bb/daint-cscs/init.sh b/.ci/bb/daint-cscs/init.sh
deleted file mode 100644
index 489b2dafdd7c269a073d1c1691a20ace4564d37b..0000000000000000000000000000000000000000
--- a/.ci/bb/daint-cscs/init.sh
+++ /dev/null
@@ -1,81 +0,0 @@
-# Initialize utility functions:
-. "$(cd "$(dirname "${BASH_SOURCE}")"; pwd)/../common_utils.sh"
-
-#
-# Initializes the environment.
-#
-init_env ()
-{
-  AUTOMAKE_ROOT='/project/d56/libcdi-ci-sw/gcc-11.2.0-haswell/automake-1.16.3-46gthis'
-  export PATH="${AUTOMAKE_ROOT}/bin:${PATH-}"
-  # Tell the custom installation of Automake where the libtool macros are:
-  export ACLOCAL_PATH="/usr/share/aclocal:${ACLOCAL_PATH-}"
-}
-
-#
-# Sets variables for tests with Cray.
-#
-init_cray ()
-{
-  init_env
-  switch_for_module craype PrgEnv-cray cce/12.0.3 cray-mpich
-
-  # Build and test against NetCDF that does not support MPI parallel invocations
-  # (parallel NetCDF4 tests are known to fail in this case when run from the
-  # user home directory on Daint):
-  switch_for_module cray-netcdf
-
-  # Uncomment the following line to test against MPI-capable NetCDF:
-  # switch_for_module cray-netcdf-hdf5parallel cray-hdf5-parallel
-
-  CC=cc
-  CXX=CC
-  FC=ftn
-  MPI_LAUNCH="$(which srun) -p cscsci -C gpu -A d56 -t 05:00"
-
-  ECCODES_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/eccodes-2.24.2-o2a4fw3'
-  PPM_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/scales-ppm-1.0.8-44zlrlu'
-  YAXT_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/yaxt-0.9.2.1-enz3pcz'
-
-  # The installations of ecCodes, PPM and YAXT do not provide '*.la' files,
-  # which would trigger the RPATH injection:
-  export LD_LIBRARY_PATH="${ECCODES_ROOT}/lib64:${PPM_ROOT}/lib:${YAXT_ROOT}/lib:${LD_LIBRARY_PATH-}"
-}
-
-#
-# Sets variables for tests with PGI.
-#
-init_pgi ()
-{
-  init_env
-  # We use deprecated versions (the most recent compatible with PGI though) of
-  # the Cray packages and have to make sure that the default versions are
-  # unloaded (otherwise, we get various warnings and errors):
-  module unload cray-mpich cray-netcdf cray-netcdf-hdf5parallel cray-hdf5 cray-hdf5-parallel
-  switch_for_module craype PrgEnv-pgi/6.0.8 pgi/20.1.1 cray-mpich/7.7.15
-
-  # Build and test against NetCDF that does not support MPI parallel invocations
-  # (parallel NetCDF4 tests are known to fail in this case when run from the
-  # user home directory on Daint):
-  switch_for_module cray-netcdf/4.7.4.0 cray-hdf5/1.12.0.0
-
-  # Uncomment the following line to test against MPI-capable NetCDF:
-  # switch_for_module cray-netcdf-hdf5parallel/4.7.4.0 cray-hdf5-parallel/1.12.0.0
-
-  CC=cc
-  CXX=CC
-  FC=ftn
-  MPI_LAUNCH="$(which srun) -p cscsci -C gpu -A d56 -t 05:00"
-
-  ECCODES_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/eccodes-2.24.2-hwtl5nr'
-  PPM_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/scales-ppm-1.0.8-z2nxqya'
-  YAXT_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/yaxt-0.9.2.1-3orop7g'
-
-  # The deprecated versions of the Cray packages are not in the default linker
-  # search path:
-  export LD_LIBRARY_PATH="${MPICH_DIR}/lib:${NETCDF_DIR}/lib:${HDF5_DIR}/lib:${LD_LIBRARY_PATH-}"
-
-  # The installations of ecCodes, PPM and YAXT do not provide '*.la' files,
-  # which would trigger the RPATH injection:
-  export LD_LIBRARY_PATH="${ECCODES_ROOT}/lib64:${PPM_ROOT}/lib:${YAXT_ROOT}/lib:${LD_LIBRARY_PATH}"
-}
diff --git a/.ci/bb/daint-cscs/test.all.cray b/.ci/bb/daint-cscs/test.all.cray
deleted file mode 100755
index 35921729d6a67d9cf0a23d77ff270aae9c9a7b0c..0000000000000000000000000000000000000000
--- a/.ci/bb/daint-cscs/test.all.cray
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-
-set -eu
-set -o pipefail
-
-script_dir=$(cd "$(dirname "$0")"; pwd)
-top_srcdir=$(cd "${script_dir}/../../.."; pwd)
-
-. "${script_dir}/init.sh"
-init_cray
-
-# Save time for the person running this script manually:
-if test "x${PE_NETCDF_MODULE_NAME}" = 'xcray-netcdf'; then
-  case $top_srcdir in
-    "${HOME}/"*)
-      echo "ERROR: parallel NetCDF4 tests are known to fail when CDI is built in the user home directory and linked against NetCDF that does not support MPI parallel invocations" >&2
-      exit 1
-  esac
-fi
-
-enable_maintainer_mode='no'
-if test ! -f "${top_srcdir}/configure"; then
-  "${top_srcdir}/autogen.sh"
-  # If there is no configure script, there are, most probably, no Fortran
-  # interface files, which are generated in the maintainer mode only:
-  enable_maintainer_mode='yes'
-fi
-
-# The configure script does not check the 'lib64' subdirectory, therefore we
-# run it with '--with-eccodes' and the following flags. Note that fixing this
-# in the configure script might be tricky: the 'lib64' subdirectory should be
-# checked first but if it does not exist or does not contain the library, we
-# might end up linking to a library from the linker's default search path
-# (e.g. /usr/lib) instead of the one from "$with_eccodes/lib" because
-# "-L${with_eccodes}/lib64" would be ignored in that case:
-CPPFLAGS="-I${ECCODES_ROOT}/include"
-LDFLAGS="-L${ECCODES_ROOT}/lib64"
-
-"${top_srcdir}/configure" \
---enable-cf-interface \
---enable-iso-c-interface \
---enable-maintainer-mode="${enable_maintainer_mode}" \
---enable-mpi \
---enable-option-checking=fatal \
---enable-ppm-dist-array \
---with-concurrent-mpi-checks \
---with-eccodes \
---with-netcdf \
-CC="${CC}" \
-CPPFLAGS="${CPPFLAGS}" \
-FC="${FC}" \
-LDFLAGS="${LDFLAGS}" \
-MPI_LAUNCH="${MPI_LAUNCH}" \
-PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig:${PKG_CONFIG_PATH}"
-
-make -j8
-
-# Run with '-j' to submit as many MPI jobs as possible
-# (see '--with-concurrent-mpi-checks'):
-make -j check || { cat tests/test-suite.log; exit 1; }
-
-check_all_tests_passed tests/test-suite.log
-
-check_no_git_untracked
diff --git a/.ci/bb/daint-cscs/test.all.pgi b/.ci/bb/daint-cscs/test.all.pgi
deleted file mode 100755
index fde1e97b07b1a79a3bbe413a5e171df7b5696b69..0000000000000000000000000000000000000000
--- a/.ci/bb/daint-cscs/test.all.pgi
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/bash
-
-set -eu
-set -o pipefail
-
-script_dir=$(cd "$(dirname "$0")"; pwd)
-top_srcdir=$(cd "${script_dir}/../../.."; pwd)
-
-. "${script_dir}/init.sh"
-init_pgi
-
-# Save time for the person running this script manually:
-if test "x${PE_NETCDF_MODULE_NAME}" = 'xcray-netcdf'; then
-  case $top_srcdir in
-    "${HOME}/"*)
-      echo "ERROR: parallel NetCDF4 tests are known to fail when CDI is built in the user home directory and linked against NetCDF that does not support MPI parallel invocations" >&2
-      exit 1
-  esac
-fi
-
-enable_maintainer_mode='no'
-if test ! -f "${top_srcdir}/configure"; then
-  "${top_srcdir}/autogen.sh"
-  # If there is no configure script, there are, most probably, no Fortran
-  # interface files, which are generated in the maintainer mode only:
-  enable_maintainer_mode='yes'
-fi
-
-# The configure script does not check the 'lib64' subdirectory, therefore we
-# run it with '--with-eccodes' and the following flags. Note that fixing this
-# in the configure script might be tricky: the 'lib64' subdirectory should be
-# checked first but if it does not exist or does not contain the library, we
-# might end up linking to a library from the linker's default search path
-# (e.g. /usr/lib) instead of the one from "$with_eccodes/lib" because
-# "-L${with_eccodes}/lib64" would be ignored in that case:
-CPPFLAGS="-I${ECCODES_ROOT}/include"
-LDFLAGS="-L${ECCODES_ROOT}/lib64"
-
-"${top_srcdir}/configure" \
---enable-cf-interface \
---enable-iso-c-interface \
---enable-maintainer-mode="${enable_maintainer_mode}" \
---enable-mpi \
---enable-option-checking=fatal \
---enable-ppm-dist-array \
---with-concurrent-mpi-checks \
---with-eccodes \
---with-netcdf \
-CC="${CC}" \
-CPPFLAGS="${CPPFLAGS}" \
-FC="${FC}" \
-LDFLAGS="${LDFLAGS}" \
-MPI_LAUNCH="${MPI_LAUNCH}" \
-PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig:${PKG_CONFIG_PATH}" \
-PTHREAD_LIBS='-lpthread'
-
-make -j8
-
-# Run with '-j' to submit as many MPI jobs as possible
-# (see '--with-concurrent-mpi-checks'):
-make -j check || { cat tests/test-suite.log; exit 1; }
-
-check_all_tests_passed tests/test-suite.log
-
-check_no_git_untracked
diff --git a/.ci/bb/levante-dkrz/init.sh b/.ci/bb/levante-dkrz/init.sh
index 5cd38af4d2e0b2dd647acea3c409982019efc731..ac1d83807eaaf5a1b38d0aec5836a70bbb0e5d23 100644
--- a/.ci/bb/levante-dkrz/init.sh
+++ b/.ci/bb/levante-dkrz/init.sh
@@ -6,7 +6,7 @@
 #
 init_env ()
 {
-  switch_for_module ruby/3.0.2-gcc-11.2.0
+  switch_for_module git ruby/3.0.2-gcc-11.2.0
 }
 
 #
diff --git a/.ci/bb/run_all.sh b/.ci/bb/run_all.sh
index bba02cd2629b4f76830910b0153bba47acea8712..f5398d01ca77666941e0cdddcbbad5758a0b87a1 100755
--- a/.ci/bb/run_all.sh
+++ b/.ci/bb/run_all.sh
@@ -16,8 +16,6 @@ case $(uname -s) in
         test_environment='breeze-mpim' ;;
       levante*.lvt.dkrz.de\ *)
         test_environment='levante-dkrz' ;;
-      daint*.login.cscs.ch\ *)
-        test_environment='daint-cscs' ;;
     esac
 esac
 
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f64790a7ae6ee4f621c48537c24bc70a0866f7b7
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,119 @@
+workflow:
+  auto_cancel:
+    on_new_commit: none
+    on_job_failure: none
+  rules:
+    - if: $CI_COMMIT_BRANCH == "master"
+    - if: $CI_COMMIT_BRANCH == "develop"
+    - if: $CI_COMMIT_BRANCH =~ /^cdi-.*-release$/
+    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+      auto_cancel:
+        on_new_commit: interruptible
+        on_job_failure: all
+    - if: $CI_PIPELINE_SOURCE == "web"
+
+stages:
+  - basic
+  - levante
+  - breeze
+
+.colorized:
+  variables:
+    DEFAULT: '\033[0m'
+    RED: '\033[0;31m'
+
+style:
+  stage: basic
+  extends: .colorized
+  variables:
+    GIT_DEPTH: 1
+    STYLE_PATCH: ${CI_PROJECT_DIR}/style.patch
+  before_script:
+    - apk add black clang-extra-tools git py3-flake8 py3-isort py3-pip python3
+  script:
+    - >-
+      clang-format --style=file -i
+      $(find src app interfaces tests examples
+      \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' \) -a
+      ! -path 'interfaces/python/cdi_wrapper.cpp' -a
+      ! -path 'interfaces/ruby/cdi_wrapper.cpp' -a
+      ! -path 'src/cdilib.c')
+    - |
+      # Test if patching is necessary
+      test ! -s ${STYLE_PATCH} || {
+        printf "${RED}The source code does not meet the style recuirements. \
+      Please, apply the patch (see artifacts).${DEFAULT}\n"
+
+        printf "${RED}Note that the result of the formatting might depend on \
+          the versions of the formatting tools. In this project, whatever \
+          formatting this CI job produces is the correct one. If it expects \
+          you to re-format parts of the source code that you did not modify, \
+          do so in a separate commit, which must not be squashed, and list the \
+          commit in the '.git-blame-ignore-revs' file.${DEFAULT}\n"
+
+        exit 1
+      }
+  artifacts:
+    paths:
+      - ${STYLE_PATCH}
+    expire_in: 60min
+    expose_as: 'Style Patch'
+    when: on_failure
+  tags:
+    -  alpine
+  interruptible: true
+
+.common:
+  needs: []
+  variables:
+    GIT_DEPTH: 1
+    TASK_COUNT: 8
+    MAKEFLAGS: --jobs=${TASK_COUNT}
+    AM_COLOR_TESTS: always
+  interruptible: true
+
+include:
+  - project: "anw_dienste/ci-templates"
+    file: ".slurm-ci.yml"
+
+.common-levante:
+  stage: levante
+  extends:
+    - .default
+    - .common
+  variables:
+    PARTITION: shared
+    TASK_COUNT: 8
+    TIME_LIMIT: "15:00"
+    SCHEDULER_PARAMETERS: >-
+      --account=ka1125
+      --partition=${PARTITION}
+      --ntasks=${TASK_COUNT}
+      --time=${TIME_LIMIT}
+      --nodes=1
+  before_script:
+    - module purge
+  script:
+    - "${CI_PROJECT_DIR}/.ci/bb/levante-dkrz/${CI_JOB_NAME}"
+
+.common-breeze:
+  stage: breeze
+  extends: .common
+  before_script:
+    - module purge
+  script:
+    - "${CI_PROJECT_DIR}/.ci/bb/breeze-mpim/${CI_JOB_NAME}"
+  tags:
+    - mpim, breeze1-3
+
+test.all.gcc:
+  extends: .common-levante
+
+test.all.intel-classic:
+  extends: .common-levante
+
+test.icon-pio.intel-classic:
+  extends: .common-levante
+
+test.icon.gcc:
+  extends: .common-levante
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 71c43b56eb83dde30767073a4375a64f8d883746..20739bda0487b03968b1c27166b5a89765b5b0cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,29 +1,38 @@
-# cmake options:
-#
-#       -DCMAKE_INSTALL_PREFIX=/path/to/install
+cmake_minimum_required( VERSION 3.30 FATAL_ERROR )
 
-cmake_minimum_required( VERSION 3.12 FATAL_ERROR )
-
-project( cdi VERSION 2.4.0 LANGUAGES C )
+project(libcdi VERSION 2.4.0 LANGUAGES C )
 set(CMAKE_C_STANDARD 11)
 
+include(CheckIncludeFile)
+
 configure_file (
   "${PROJECT_SOURCE_DIR}/cmake/cdi_config.h.in"
-  "${PROJECT_BINARY_DIR}/config.h"
+  "${PROJECT_SOURCE_DIR}/src/config.h"
   )
 
-include_directories("${PROJECT_BINARY_DIR}")
-
-list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-
-find_package(NetCDF)
+find_package(hdf5 REQUIRED)
+if(hdf5_FOUND)
+    message(STATUS "HDF5 shaed found")
+else()
+    message(FATAL_ERROR "HDF shared not found")
+endif()
+
+#NetCDF
+find_package(netCDF COMPONENTS C REQUIRED)
+set(netcdf_flag HAVE_LIBNETCDF)
+set(netcdf_flag ${HAVE_LIBNETCDF})
+check_include_files("netcdf.h" ${netcdf_flag} C)
+if (${netCDF_FOUND})
+    message(STATUS "added compile definition HAVE_LIBNETCDF=${netCDF_FOUND}")
+    add_compile_definitions(HAVE_LIBNETCDF=${netCDF_FOUND})
+else()
+  message(WARNING "netcdf not found, compiling without netcdf")
+endif ()
 
-set(HAVE_NETCDF ${netCDF_FOUND} )
 
-if (netCDF_FOUND)
-  set(HAVE_NETCDF 1)
-endif ()
+#adding subdirectories
+## lib and general files
+add_subdirectory(src)
+## cdi executable
+add_subdirectory(app)
 
-add_subdirectory( src )
-add_subdirectory( app )
-#target_link_libraries(cdi PRIVATE NetCDF)
diff --git a/ChangeLog b/ChangeLog
index be3386e10bbc5c5522d4bd83dfa96b02761d81d6..60d0a39cd565c2e01a08634b16d6a5fcfd979c00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2024-11-28  Uwe Schulzweida
+
+        * using CGRIBEX library version 2.3.1
+	* Version 2.5.0 released
+
+2024-11-23  Uwe Schulzweida
+
+	* NetCDF: improved HealPIX support
+
+2024-11-04  Uwe Schulzweida
+
+	* reset chunktype if z and t are chunked
+
+2024-10-24  Uwe Schulzweida
+
+	* lock access to NCZARR in CDI_Threadsafe mode
+	* Renamed interface functions streamXXXRecord to streamXXXField
+
+2024-10-22  Uwe Schulzweida
+
+	* NetCDF: search for time dimension only if it is undefined
+
+2024-10-21  Uwe Schulzweida
+
+	* NetCDF: use positive attribute only for variables with undefined status
+
+2024-09-19  Uwe Schulzweida
+
+	* Version 2.4.4 released
+
+2024-09-18  Uwe Schulzweida
+
+	* absolute timeaxis failed with timeunits seconds [Bug #11916]
+
 2024-08-14  Uwe Schulzweida
 
 	* Version 2.4.3 released
diff --git a/NEWS b/NEWS
index 358f410f56ea015f82b75fc039c596b33b527c0c..d21b4942d545009488a8b484d6f3d109096da300 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,26 @@
 CDI NEWS
 --------
 
+Version 2.5.0 (28 Nov 2024):
+
+   Changes:
+     * NetCDF: improved HealPIX support
+     * reset chunktype if z and t are chunked
+     * lock access to NCZARR in CDI_Threadsafe mode
+
+Version 2.4.4 (19 Sep 2024):
+
+   Fixed bugs:
+     * absolute timeaxis failed with timeunits seconds [Bug #11916]
+
+Version 2.4.2 (21 Jun 2024):
+
+   Changes:
+     * NetCDF4: improved calculation of input chunk cache size
+     * NetCDF4: switched off output chunk cache
+   Fixed bugs:
+     * cdiInqContents: missing lock of non thread-safe netCDF4/HDF5 calls (bug fix)
+
 Version 2.4.1 (21 May 2024):
 
    Changes:
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 22bca89f702b3c330d8e9cfdf9f2ff7d493f6f4c..ce87f49683bff30ea6f52c4f06e33dc4d1bf135e 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -7,6 +7,6 @@ target_include_directories(cdi PUBLIC
   $<INSTALL_INTERFACE:include
 )
 
-target_link_libraries(cdi PUBLIC cdilib)
+target_link_libraries(cdi PUBLIC cdilib netCDF::netcdf ${HDF5_LIBS} pthread)
 
 target_compile_definitions(cdi PUBLIC HAVE_CONFIG_H)
diff --git a/app/cdi.c b/app/cdi.c
index 0ff261e87665efcae74d8f730043966ef66ee978..819d74e3c1cd69eedde49f4a3eb764ab1483e6b1 100644
--- a/app/cdi.c
+++ b/app/cdi.c
@@ -175,8 +175,8 @@ usage(void)
   fprintf(stderr, "    -E             Use ecCodes to decode/encode GRIB1 messages\n");
   fprintf(stderr, "    -f <format>    Format of the output file. (grb, grb2, nc, nc2, nc4, nc4c, nc5, nczarr, srv, ext or ieg)\n");
   fprintf(stderr, "    -i <num>       Number of worker to decode/decompress GRIB records\n");
-  fprintf(stderr, "    -m             Move records\n");
-  fprintf(stderr, "    -r             Use CDI record API\n");
+  fprintf(stderr, "    -m             Move fields\n");
+  fprintf(stderr, "    -r             Use CDI field API\n");
   fprintf(stderr, "    -s             give short information if ofile is missing\n");
   fprintf(stderr, "    -T             Pre scan hole GRIB file to get the number of timesteps\n");
   fprintf(stderr, "    -t <table>     Parameter table name/file\n");
@@ -765,7 +765,7 @@ main(int argc, char *argv[])
   char *wTable = NULL;
   bool preScan = false;
   int Move = 0;
-  int Record = 0;
+  int Field = 0;
   int Variable = 0;
   int Debug = 0;
   int Vardis = 0;
@@ -816,7 +816,7 @@ main(int argc, char *argv[])
 	case 'N': queryNames[numQueryNames++] = strdup(optarg); break;
 	case 'n': Info = 0;  NoInfo = 1;  break;
 	case 'R': cdiDefGlobal("REGULARGRID", 1); break;
-	case 'r': Record = 1; break;
+	case 'r': Field = 1; break;
 	case 'X': Variable = 1; break;
 	case 'S': queryStepidx[numQueryStepidx++] = atoi(optarg); break;
 	case 's': Shortinfo = 1; break;
@@ -976,12 +976,12 @@ main(int argc, char *argv[])
 
             CdiDateTime vdatetime = taxisInqVdatetime(taxisID1);
 
-            if (Record)
+            if (Field)
               {
                 for (recID = 0; recID < nrecs; recID++)
                   {
-                    streamInqRecord(streamID1, &varID, &levelID);
-                    streamReadRecord(streamID1, data, &nmiss);
+                    streamInqField(streamID1, &varID, &levelID);
+                    streamReadField(streamID1, data, &nmiss);
 
                     int number = vlistInqVarNumber(vlistID1, varID);
                     int gridID = vlistInqVarGrid(vlistID1, varID);
@@ -1006,11 +1006,11 @@ main(int argc, char *argv[])
 
                     if (fname2)
                       {
-                        streamDefRecord(streamID2, varID, levelID);
+                        streamDefField(streamID2, varID, levelID);
                         if (Move)
-                          streamCopyRecord(streamID2, streamID1);
+                          streamCopyField(streamID2, streamID1);
                         else
-                          streamWriteRecord(streamID2, data, nmiss);
+                          streamWriteField(streamID2, data, nmiss);
                       }
                   }
               }
diff --git a/configure.ac b/configure.ac
index d5384fae6f61b49e8ffb6bbc6f04465e55d9a557..caa057f45a4237c314588e343f073fcbedc14504 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
 AC_PREREQ([2.69])
 LT_PREREQ([2.4.6])
 
-AC_INIT([cdi],[2.4.3],[https://mpimet.mpg.de/cdi])
+AC_INIT([cdi],[2.5.0],[https://mpimet.mpg.de/cdi])
 AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
 
 AC_CONFIG_AUX_DIR([config])
diff --git a/doc/tex/cdi_cman.tex b/doc/tex/cdi_cman.tex
index d33aa7943e9840dc49d90f1803982a6c8cbc88d6..f1c152aec41847d25995bff78846c6dbdfd9af6a 100644
--- a/doc/tex/cdi_cman.tex
+++ b/doc/tex/cdi_cman.tex
@@ -136,7 +136,7 @@
 \end{picture}
 
 \begin{flushright}
-{\large\bfseries Climate Data Interface \\ Version 2.4.0 \\ February 2024}
+{\large\bfseries Climate Data Interface \\ Version 2.5.0 \\ November 2024}
 \end{flushright}
 
 \vfill
diff --git a/doc/tex/cdi_fman.tex b/doc/tex/cdi_fman.tex
index ef3d9edbc92473b690ff9cb4b1a40cfd6379cae0..3058229d9750e4f693bd20398e06ead7608011b3 100644
--- a/doc/tex/cdi_fman.tex
+++ b/doc/tex/cdi_fman.tex
@@ -133,7 +133,7 @@
 \end{picture}
 
 \begin{flushright}
-{\large\bfseries Climate Data Interface \\ Version 2.4.0 \\ February 2024}
+{\large\bfseries Climate Data Interface \\ Version 2.5.0 \\ November 2024}
 \end{flushright}
 
 \vfill
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3d2dc7e693e16780f4b8e4fdcca1d2725de8e272..1f88fe09b84956160e7b52fb11ea0605f0b274a3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -142,5 +142,7 @@ add_library(cdilib
   ${cdi_src_files}
 #  INSTALL_HEADERS_LIST  cdi.h
 )
+find_package(HDF5 REQUIRED COMPONENTS C REQUIRED)
 
+target_link_libraries(cdilib PUBLIC netCDF::netcdf ${HDF5_LIBS})
 target_compile_definitions(cdilib PUBLIC HAVE_CONFIG_H)
diff --git a/src/cdf.c b/src/cdf.c
index f0faf003410481bb7a27d569d47e79217dcaf933..78e7fff9ff3579a3718212be6e11917fdf186367 100644
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -199,6 +199,8 @@ cdf4Open(const char *filename, const char *mode, int *filetype)
 static void
 cdfCloseFile(int fileID)
 {
+
+  if (CDF_Debug) Message( "Closing cdf file: %d", fileID);
   cdf_close(fileID);
 }
 
diff --git a/src/cdf_read.c b/src/cdf_read.c
index a5d1f836a2e7c16b850c211e410bec1e82083ffd..05622e06081bc7bfa5e099e941303d242be8c217 100644
--- a/src/cdf_read.c
+++ b/src/cdf_read.c
@@ -944,7 +944,7 @@ cdf_read_next_record(stream_t *streamptr, int recID, int memtype, void *data, si
 }
 
 void
-cdf_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
+cdf_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
 {
   int tsID = streamptr->curTsID;
   int vrecID = streamptr->tsteps[tsID].curRecID;
diff --git a/src/cdf_records.c b/src/cdf_records.c
index 5e179588cd65309681121926d45e78bb858e58b1..1ad97c2a7d8aa5f25b0fcf4306e68117ffabaa81 100644
--- a/src/cdf_records.c
+++ b/src/cdf_records.c
@@ -82,19 +82,19 @@ cdf_create_records(stream_t *streamptr, size_t tsID)
   tsteps_t *sourceTstep = streamptr->tsteps;
   tsteps_t *destTstep = sourceTstep + tsID;
 
-  int numRecs = vlistNumRecords(vlistID);
-  if (numRecs <= 0) return;
+  int numFields = vlistNumFields(vlistID);
+  if (numFields <= 0) return;
 
   if (tsID == 0)
     {
-      int numRecsAvail = numRecs;  // use all records at first timestep
+      int numRecsAvail = numFields;  // use all records at first timestep
 
-      streamptr->nrecs += numRecs;
+      streamptr->nrecs += numFields;
 
-      cdf_init_timestep(destTstep, numRecs, numRecsAvail);
+      cdf_init_timestep(destTstep, numFields, numRecsAvail);
 
       destTstep->recIDs = (int *) Malloc((size_t) numRecsAvail * sizeof(int));
-      cdf_init_records_step0(numRecs, destTstep->recIDs, destTstep->records, vlistID);
+      cdf_init_records_step0(numFields, destTstep->recIDs, destTstep->records, vlistID);
     }
   else if (tsID == 1)
     {
@@ -102,14 +102,14 @@ cdf_create_records(stream_t *streamptr, size_t tsID)
 
       streamptr->nrecs += numRecsAvail;
 
-      cdf_init_timestep(destTstep, numRecs, numRecsAvail);
+      cdf_init_timestep(destTstep, numFields, numRecsAvail);
 
-      memcpy(destTstep->records, sourceTstep->records, (size_t) numRecs * sizeof(record_t));
+      memcpy(destTstep->records, sourceTstep->records, (size_t) numFields * sizeof(record_t));
 
       if (numRecsAvail)
         {
           destTstep->recIDs = (int *) Malloc((size_t) numRecsAvail * sizeof(int));
-          cdf_init_records_step1(numRecs, destTstep->recIDs, destTstep->records, vlistID);
+          cdf_init_records_step1(numFields, destTstep->recIDs, destTstep->records, vlistID);
         }
     }
   else
@@ -120,9 +120,9 @@ cdf_create_records(stream_t *streamptr, size_t tsID)
 
       streamptr->nrecs += numRecsAvail;
 
-      cdf_init_timestep(destTstep, numRecs, numRecsAvail);
+      cdf_init_timestep(destTstep, numFields, numRecsAvail);
 
-      memcpy(destTstep->records, sourceTstep->records, (size_t) numRecs * sizeof(record_t));
+      memcpy(destTstep->records, sourceTstep->records, (size_t) numFields * sizeof(record_t));
 
       if (numRecsAvail)
         {
diff --git a/src/cdf_write.c b/src/cdf_write.c
index 521802dc209a9059abcfe7ba78acfe8ff578359a..eb556afcac38904a2ddbc11224283458fb6d6c16 100644
--- a/src/cdf_write.c
+++ b/src/cdf_write.c
@@ -1638,7 +1638,7 @@ cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, co
 }
 
 void
-cdf_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals)
+cdf_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals)
 {
   int varID = streamptr->record->varID;
   int levelID = streamptr->record->levelID;
diff --git a/src/cdi.h b/src/cdi.h
index bbe58c112e726faf6a39d6dde07007bf93629e34..624905c5dda1551c5803546224f815d35db79c47 100644
--- a/src/cdi.h
+++ b/src/cdi.h
@@ -353,6 +353,10 @@ int     cdiEncodeTime(int hour, int minute, int second);
 int     cdiGetFiletype(const char *uri, int *byteorder);
 int     cdiGetProtocol(const char *uri, const char **filename);
 
+int     streamOpenReadNCMem(int ncid);
+int     streamOpenWriteNCMem(int ncid);
+void    streamCloseNCMem(int ncid);
+
 //      streamOpenRead: Open a dataset for reading
 int     streamOpenRead(const char *path);
 
@@ -443,15 +447,15 @@ void    streamWriteVarChunk(int streamID, int varID, const int rect[][2], const
 void    streamWriteVarChunkF(int streamID, int varID, const int rect[][2], const float data[], SizeType numMissVals);
 
 
-// STREAM record I/O routines (sequential access)
+// STREAM field I/O routines (sequential access)
 
-void    streamDefRecord(int streamID, int  varID, int  levelID);
-void    streamInqRecord(int streamID, int *varID, int *levelID);
-void    streamWriteRecord(int streamID, const double data[], SizeType numMissVals);
-void    streamWriteRecordF(int streamID, const float data[], SizeType numMissVals);
-void    streamReadRecord(int streamID, double data[], SizeType *numMissVals);
-void    streamReadRecordF(int streamID, float data[], SizeType *numMissVals);
-void    streamCopyRecord(int streamIDdest, int streamIDsrc);
+void    streamDefField(int streamID, int  varID, int  levelID);
+void    streamInqField(int streamID, int *varID, int *levelID);
+void    streamWriteField(int streamID, const double data[], SizeType numMissVals);
+void    streamWriteFieldF(int streamID, const float data[], SizeType numMissVals);
+void    streamReadField(int streamID, double data[], SizeType *numMissVals);
+void    streamReadFieldF(int streamID, float data[], SizeType *numMissVals);
+void    streamCopyField(int streamIDdest, int streamIDsrc);
 
 void    streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum);
 
@@ -565,7 +569,7 @@ int     vlistZaxis(int vlistID, int index);
 int     vlistZaxisIndex(int vlistID, int zaxisID);
 void    vlistChangeZaxisIndex(int vlistID, int index, int zaxisID);
 void    vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2);
-int     vlistNumRecords(int vlistID);
+int     vlistNumFields(int vlistID);
 int     vlistSubtype(int vlistID, int index);
 int     vlistSubtypeIndex(int vlistID, int subtypeID);
 
diff --git a/src/cdi_int.h b/src/cdi_int.h
index fd31cd2d5fc03b5ba4aeac6ca1b1cfd084c3140e..847b95d36ee2e02b362cba2e4253ae8c82086fc3 100644
--- a/src/cdi_int.h
+++ b/src/cdi_int.h
@@ -55,7 +55,7 @@ bool strStartsWith(const char *vstr, const char *cstr);
 static inline bool
 str_is_equal(const char *x, const char *y)
 {
-  return (*x == *y) && strcmp(x, y) == 0;
+  return (*x == *y) && (strcmp(x, y) == 0);
 }
 
 #ifndef M_PI
diff --git a/src/cgribex.h b/src/cgribex.h
index afb23c6150602b56bbd7519ceaeb657663528a27..892511532a44384d54fc69fad679b0cf445ee47c 100644
--- a/src/cgribex.h
+++ b/src/cgribex.h
@@ -31,29 +31,29 @@
 #define  GRIB1_LTYPE_LANDDEPTH           111
 #define  GRIB1_LTYPE_LANDDEPTH_LAYER     112
 #define  GRIB1_LTYPE_ISENTROPIC          113
-#define  GRIB1_LTYPE_SEADEPTH            160  // Depth Below Sea Level                                 
-#define  GRIB1_LTYPE_LAKE_BOTTOM         162  // Lake or River Bottom                                  
-#define  GRIB1_LTYPE_SEDIMENT_BOTTOM     163  // Bottom Of Sediment Layer                              
-#define  GRIB1_LTYPE_SEDIMENT_BOTTOM_TA  164  // Bottom Of Thermally Active Sediment Layer             
-#define  GRIB1_LTYPE_SEDIMENT_BOTTOM_TW  165  // Bottom Of Sediment Layer Penetrated By Thermal Wave   
-#define  GRIB1_LTYPE_MIX_LAYER           166  // Mixing Layer                                          
+#define  GRIB1_LTYPE_SEADEPTH            160  // Depth Below Sea Level
+#define  GRIB1_LTYPE_LAKE_BOTTOM         162  // Lake or River Bottom
+#define  GRIB1_LTYPE_SEDIMENT_BOTTOM     163  // Bottom Of Sediment Layer
+#define  GRIB1_LTYPE_SEDIMENT_BOTTOM_TA  164  // Bottom Of Thermally Active Sediment Layer
+#define  GRIB1_LTYPE_SEDIMENT_BOTTOM_TW  165  // Bottom Of Sediment Layer Penetrated By Thermal Wave
+#define  GRIB1_LTYPE_MIX_LAYER           166  // Mixing Layer
 
 // GRIB1 Data representation type (Grid Type) [Table 6]
-#define  GRIB1_GTYPE_LATLON                0  //  latitude/longitude                                   
-#define  GRIB1_GTYPE_LATLON_ROT           10  //  rotated latitude/longitude                           
-#define  GRIB1_GTYPE_LATLON_STR           20  //  stretched latitude/longitude                         
-#define  GRIB1_GTYPE_LATLON_ROTSTR        30  //  rotated and stretched latitude/longitude             
-#define  GRIB1_GTYPE_GAUSSIAN              4  //  gaussian grid                                        
-#define  GRIB1_GTYPE_GAUSSIAN_ROT         14  //  rotated gaussian grid                                
-#define  GRIB1_GTYPE_GAUSSIAN_STR         24  //  stretched gaussian grid                              
-#define  GRIB1_GTYPE_GAUSSIAN_ROTSTR      34  //  rotated and stretched gaussian grid                  
-#define  GRIB1_GTYPE_LCC                   3  //  Lambert conformal                                    
-#define  GRIB1_GTYPE_SPECTRAL             50  //  spherical harmonics                                  
-#define  GRIB1_GTYPE_GME                 192  //  hexagonal GME grid                                   
+#define  GRIB1_GTYPE_LATLON                0  //  latitude/longitude
+#define  GRIB1_GTYPE_LATLON_ROT           10  //  rotated latitude/longitude
+#define  GRIB1_GTYPE_LATLON_STR           20  //  stretched latitude/longitude
+#define  GRIB1_GTYPE_LATLON_ROTSTR        30  //  rotated and stretched latitude/longitude
+#define  GRIB1_GTYPE_GAUSSIAN              4  //  gaussian grid
+#define  GRIB1_GTYPE_GAUSSIAN_ROT         14  //  rotated gaussian grid
+#define  GRIB1_GTYPE_GAUSSIAN_STR         24  //  stretched gaussian grid
+#define  GRIB1_GTYPE_GAUSSIAN_ROTSTR      34  //  rotated and stretched gaussian grid
+#define  GRIB1_GTYPE_LCC                   3  //  Lambert conformal
+#define  GRIB1_GTYPE_SPECTRAL             50  //  spherical harmonics
+#define  GRIB1_GTYPE_GME                 192  //  hexagonal GME grid
 
 // Macros for the indicator section ( Section 0 )
-#define  ISEC0_GRIB_Len             (isec0[ 0])  //  Number of octets in the GRIB message              
-#define  ISEC0_GRIB_Version         (isec0[ 1])  //  GRIB edition number                               
+#define  ISEC0_GRIB_Len             (isec0[ 0])  //  Number of octets in the GRIB message
+#define  ISEC0_GRIB_Version         (isec0[ 1])  //  GRIB edition number
 
 
 // Macros for the product definition section ( Section 1 )
@@ -67,108 +67,108 @@
 #define  ISEC1_TABLE4_30MINUTES  14
 
 
-#define  ISEC1_CodeTable            (isec1[ 0])  //  Version number of code table                 
-#define  ISEC1_CenterID             (isec1[ 1])  //  Identification of centre                     
-#define  ISEC1_ModelID              (isec1[ 2])  //  Identification of model                      
-#define  ISEC1_GridDefinition       (isec1[ 3])  //  Grid definition                              
-#define  ISEC1_Sec2Or3Flag          (isec1[ 4])  //  Section 2 or 3 included                      
-#define  ISEC1_Parameter            (isec1[ 5])  //  Parameter indicator                          
-#define  ISEC1_LevelType            (isec1[ 6])  //  Type of level indicator                      
-#define  ISEC1_Level1               (isec1[ 7])  //  Level 1                                      
-#define  ISEC1_Level2               (isec1[ 8])  //  Level 2                                      
-#define  ISEC1_Year                 (isec1[ 9])  //  Year of century (YY)                         
-#define  ISEC1_Month                (isec1[10])  //  Month (MM)                                   
-#define  ISEC1_Day                  (isec1[11])  //  Day (DD)                                     
-#define  ISEC1_Hour                 (isec1[12])  //  Hour (HH)                                    
-#define  ISEC1_Minute               (isec1[13])  //  Minute (MM)                                  
-#define  ISEC1_TimeUnit             (isec1[14])  //  Time unit indicator                          
-#define  ISEC1_TimePeriod1          (isec1[15])  //  P1 Time period                               
-#define  ISEC1_TimePeriod2          (isec1[16])  //  P2 Time period                               
-#define  ISEC1_TimeRange            (isec1[17])  //  Time range indicator                         
-#define  ISEC1_AvgNum               (isec1[18])  //  Number of products included in an average    
-#define  ISEC1_AvgMiss              (isec1[19])  //  Number of products missing from an average   
-#define  ISEC1_Century              (isec1[20])  //  Century                                      
-#define  ISEC1_SubCenterID          (isec1[21])  //  Subcenter identifier                         
-#define  ISEC1_DecScaleFactor       (isec1[22])  //  Decimal scale factor                         
-#define  ISEC1_LocalFLag            (isec1[23])  //  Flag field to indicate local use in isec1    
+#define  ISEC1_CodeTable            (isec1[ 0])  //  Version number of code table
+#define  ISEC1_CenterID             (isec1[ 1])  //  Identification of centre
+#define  ISEC1_ModelID              (isec1[ 2])  //  Identification of model
+#define  ISEC1_GridDefinition       (isec1[ 3])  //  Grid definition
+#define  ISEC1_Sec2Or3Flag          (isec1[ 4])  //  Section 2 or 3 included
+#define  ISEC1_Parameter            (isec1[ 5])  //  Parameter indicator
+#define  ISEC1_LevelType            (isec1[ 6])  //  Type of level indicator
+#define  ISEC1_Level1               (isec1[ 7])  //  Level 1
+#define  ISEC1_Level2               (isec1[ 8])  //  Level 2
+#define  ISEC1_Year                 (isec1[ 9])  //  Year of century (YY)
+#define  ISEC1_Month                (isec1[10])  //  Month (MM)
+#define  ISEC1_Day                  (isec1[11])  //  Day (DD)
+#define  ISEC1_Hour                 (isec1[12])  //  Hour (HH)
+#define  ISEC1_Minute               (isec1[13])  //  Minute (MM)
+#define  ISEC1_TimeUnit             (isec1[14])  //  Time unit indicator
+#define  ISEC1_TimePeriod1          (isec1[15])  //  P1 Time period
+#define  ISEC1_TimePeriod2          (isec1[16])  //  P2 Time period
+#define  ISEC1_TimeRange            (isec1[17])  //  Time range indicator
+#define  ISEC1_AvgNum               (isec1[18])  //  Number of products included in an average
+#define  ISEC1_AvgMiss              (isec1[19])  //  Number of products missing from an average
+#define  ISEC1_Century              (isec1[20])  //  Century
+#define  ISEC1_SubCenterID          (isec1[21])  //  Subcenter identifier
+#define  ISEC1_DecScaleFactor       (isec1[22])  //  Decimal scale factor
+#define  ISEC1_LocalFLag            (isec1[23])  //  Flag field to indicate local use in isec1
 
 #define  ISEC1_ECMWF_LocalExtension (isec1[36])
 #define  ISEC1_ECMWF_Class          (isec1[37])
 
 
 // Macros for the grid definition section ( Section 2 )
-#define  ISEC2_GridType             (isec2[ 0])  // Data representation type 
+#define  ISEC2_GridType             (isec2[ 0])  // Data representation type
 
 // Triangular grids
 
-#define  ISEC2_GME_NI2              (isec2[ 1])  //  Number of factor 2 in factorisation of Ni    
-#define  ISEC2_GME_NI3              (isec2[ 2])  //  Number of factor 3 in factorisation of Ni    
-#define  ISEC2_GME_ND               (isec2[ 3])  //  Nubmer of diamonds                           
-#define  ISEC2_GME_NI               (isec2[ 4])  //  Number of tri. subdiv. of the icosahedron    
-#define  ISEC2_GME_AFlag            (isec2[ 5])  //  Flag for orientation of diamonds (Table A)   
-#define  ISEC2_GME_LatPP            (isec2[ 6])  //  Latitude of pole point                       
-#define  ISEC2_GME_LonPP            (isec2[ 7])  //  Longitude of pole point                      
-#define  ISEC2_GME_LonMPL           (isec2[ 8])  //  Longitude of the first diamond               
-#define  ISEC2_GME_BFlag            (isec2[ 9])  //  Flag for storage sequence (Table B)          
+#define  ISEC2_GME_NI2              (isec2[ 1])  //  Number of factor 2 in factorisation of Ni
+#define  ISEC2_GME_NI3              (isec2[ 2])  //  Number of factor 3 in factorisation of Ni
+#define  ISEC2_GME_ND               (isec2[ 3])  //  Nubmer of diamonds
+#define  ISEC2_GME_NI               (isec2[ 4])  //  Number of tri. subdiv. of the icosahedron
+#define  ISEC2_GME_AFlag            (isec2[ 5])  //  Flag for orientation of diamonds (Table A)
+#define  ISEC2_GME_LatPP            (isec2[ 6])  //  Latitude of pole point
+#define  ISEC2_GME_LonPP            (isec2[ 7])  //  Longitude of pole point
+#define  ISEC2_GME_LonMPL           (isec2[ 8])  //  Longitude of the first diamond
+#define  ISEC2_GME_BFlag            (isec2[ 9])  //  Flag for storage sequence (Table B)
 
 // Spherical harmonic coeficients
 
-#define  ISEC2_PentaJ               (isec2[ 1])  //  J pentagonal resolution parameter            
-#define  ISEC2_PentaK               (isec2[ 2])  //  K pentagonal resolution parameter            
-#define  ISEC2_PentaM               (isec2[ 3])  //  M pentagonal resolution parameter            
-#define  ISEC2_RepType              (isec2[ 4])  //  Representation type                          
-#define  ISEC2_RepMode              (isec2[ 5])  //  Representation mode                          
+#define  ISEC2_PentaJ               (isec2[ 1])  //  J pentagonal resolution parameter
+#define  ISEC2_PentaK               (isec2[ 2])  //  K pentagonal resolution parameter
+#define  ISEC2_PentaM               (isec2[ 3])  //  M pentagonal resolution parameter
+#define  ISEC2_RepType              (isec2[ 4])  //  Representation type
+#define  ISEC2_RepMode              (isec2[ 5])  //  Representation mode
 
 // Gaussian grids
 
-#define  ISEC2_NumLon               (isec2[ 1])  //  Number of points along a parallel (Ni)       
-#define  ISEC2_NumLat               (isec2[ 2])  //  Number of points along a meridian (Nj)       
-#define  ISEC2_FirstLat             (isec2[ 3])  //  Latitude of the first grid point             
-#define  ISEC2_FirstLon             (isec2[ 4])  //  Longitude of the first grid point            
-#define  ISEC2_ResFlag              (isec2[ 5])  //  Resolution flag: 128 regular grid            
-#define  ISEC2_LastLat              (isec2[ 6])  //  Latitude of the last grid point              
-#define  ISEC2_LastLon              (isec2[ 7])  //  Longitude of the last grid point             
-#define  ISEC2_LonIncr              (isec2[ 8])  //  i direction increment                        
-#define  ISEC2_LatIncr              (isec2[ 9])  //  j direction increment                        
+#define  ISEC2_NumLon               (isec2[ 1])  //  Number of points along a parallel (Ni)
+#define  ISEC2_NumLat               (isec2[ 2])  //  Number of points along a meridian (Nj)
+#define  ISEC2_FirstLat             (isec2[ 3])  //  Latitude of the first grid point
+#define  ISEC2_FirstLon             (isec2[ 4])  //  Longitude of the first grid point
+#define  ISEC2_ResFlag              (isec2[ 5])  //  Resolution flag: 128 regular grid
+#define  ISEC2_LastLat              (isec2[ 6])  //  Latitude of the last grid point
+#define  ISEC2_LastLon              (isec2[ 7])  //  Longitude of the last grid point
+#define  ISEC2_LonIncr              (isec2[ 8])  //  i direction increment
+#define  ISEC2_LatIncr              (isec2[ 9])  //  j direction increment
 #define  ISEC2_NumPar               (isec2[ 9])  //  Number of parallels between a pole and the E.
-#define  ISEC2_ScanFlag             (isec2[10])  //  Scanning mode flags                          
-#define  ISEC2_NumVCP               (isec2[11])  //  Number of vertical coordinate parameters     
+#define  ISEC2_ScanFlag             (isec2[10])  //  Scanning mode flags
+#define  ISEC2_NumVCP               (isec2[11])  //  Number of vertical coordinate parameters
 
 // Lambert
 
-#define  ISEC2_Lambert_Lov          (isec2[ 6])  //  Orientation of the grid                      
-#define  ISEC2_Lambert_dx           (isec2[ 8])  //  X-direction grid length                      
-#define  ISEC2_Lambert_dy           (isec2[ 9])  //  Y-direction grid length                      
-#define  ISEC2_Lambert_ProjFlag     (isec2[12])  //  Projection centre flag                       
-#define  ISEC2_Lambert_LatS1        (isec2[13])  //  First lat at which the secant cone cuts the sphere 
-#define  ISEC2_Lambert_LatS2        (isec2[14])  //  Second lat at which the secant cone cuts the sphere 
-#define  ISEC2_Lambert_LatSP        (isec2[19])  //  Latitude of the southern pole                
-#define  ISEC2_Lambert_LonSP        (isec2[20])  //  Longitude of the southern pole               
+#define  ISEC2_Lambert_Lov          (isec2[ 6])  //  Orientation of the grid
+#define  ISEC2_Lambert_dx           (isec2[ 8])  //  X-direction grid length
+#define  ISEC2_Lambert_dy           (isec2[ 9])  //  Y-direction grid length
+#define  ISEC2_Lambert_ProjFlag     (isec2[12])  //  Projection centre flag
+#define  ISEC2_Lambert_LatS1        (isec2[13])  //  First lat at which the secant cone cuts the sphere
+#define  ISEC2_Lambert_LatS2        (isec2[14])  //  Second lat at which the secant cone cuts the sphere
+#define  ISEC2_Lambert_LatSP        (isec2[19])  //  Latitude of the southern pole
+#define  ISEC2_Lambert_LonSP        (isec2[20])  //  Longitude of the southern pole
 
 
-#define  ISEC2_Reduced              (isec2[16])  // 0: regular, 1: reduced grid                   
+#define  ISEC2_Reduced              (isec2[16])  // 0: regular, 1: reduced grid
 
 #define  ISEC2_ReducedPointsPtr     (&isec2[22])
-#define  ISEC2_ReducedPoints(i)     (isec2[22+i]) // Number of points along each parallel         
+#define  ISEC2_ReducedPoints(i)     (isec2[22+i]) // Number of points along each parallel
 
 
-#define  ISEC2_LatSP                (isec2[12])  // Latitude of the southern pole of rotation     
-#define  ISEC2_LonSP                (isec2[13])  // Longitude of the southern pole of rotation    
+#define  ISEC2_LatSP                (isec2[12])  // Latitude of the southern pole of rotation
+#define  ISEC2_LonSP                (isec2[13])  // Longitude of the southern pole of rotation
 
-#define  FSEC2_RotAngle             (fsec2[ 0])  // Angle of rotation                             
-#define  FSEC2_StrFact              (fsec2[ 1])  // Stretching factor                             
+#define  FSEC2_RotAngle             (fsec2[ 0])  // Angle of rotation
+#define  FSEC2_StrFact              (fsec2[ 1])  // Stretching factor
 
 // Macros for the bit map section ( Section 3 )
 
-#define  ISEC3_PredefBitmap         (isec3[ 0])  // Predefined bitmap                             
-#define  ISEC3_MissVal              (isec3[ 1])  // Missing data value for integers               
-#define  FSEC3_MissVal              (fsec3[ 1])  // Missing data value for floats                 
+#define  ISEC3_PredefBitmap         (isec3[ 0])  // Predefined bitmap
+#define  ISEC3_MissVal              (isec3[ 1])  // Missing data value for integers
+#define  FSEC3_MissVal              (fsec3[ 1])  // Missing data value for floats
 
 // Macros for the binary data section ( Section 4 )
 
-#define  ISEC4_NumValues            (isec4[ 0])  // Number of data values for encode/decode       
-#define  ISEC4_NumBits              (isec4[ 1])  // Number of bits used for each encoded value    
-#define  ISEC4_NumNonMissValues     (isec4[20])  // Number of non-missing values                  
+#define  ISEC4_NumValues            (isec4[ 0])  // Number of data values for encode/decode
+#define  ISEC4_NumBits              (isec4[ 1])  // Number of bits used for each encoded value
+#define  ISEC4_NumNonMissValues     (isec4[20])  // Number of non-missing values
 
 
 #ifdef __cplusplus
@@ -247,6 +247,9 @@ int   grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer,
 double calculate_pfactor_float(const float* spectralField, long fieldTruncation, long subsetTruncation);
 double calculate_pfactor_double(const double* spectralField, long fieldTruncation, long subsetTruncation);
 
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp, unsigned char **gdsp, unsigned char **bmsp,
+                  unsigned char **bdsp, long *gribrecsize);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/src/cgribexlib.c b/src/cgribexlib.c
index a19337c13e190a9af685feea5cd8497e3b124761..d1786fdb3f92f03a25b3281075ebed8795cd8f77 100644
--- a/src/cgribexlib.c
+++ b/src/cgribexlib.c
@@ -1,7 +1,7 @@
 
-// Automatically generated by m214003 at 2024-06-08, do not edit
+// Automatically generated by m214003 at 2024-10-30, do not edit
 
-// CGRIBEXLIB_VERSION="2.3.0"
+// CGRIBEXLIB_VERSION="2.3.1"
 
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined(__clang__)
 #pragma GCC diagnostic push
@@ -1219,8 +1219,13 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_ar
 #define GRIBPACK unsigned char
 
 #ifndef HOST_ENDIANNESS
+#ifdef __cplusplus
+static const uint32_t HOST_ENDIANNESS_temp[1] = { UINT32_C(0x00030201) };
+#define HOST_ENDIANNESS (((const unsigned char *) HOST_ENDIANNESS_temp)[0])
+#else
 #define HOST_ENDIANNESS (((const unsigned char *) &(const uint32_t[1]){ UINT32_C(0x00030201) })[0])
 #endif
+#endif
 
 #define IS_BIGENDIAN() (HOST_ENDIANNESS == 0)
 #define Error(x, y)
@@ -1948,16 +1953,16 @@ decfp2(int kexp, int kmant)
   /*   Section 2 . Convert other values.                               */
   /* ----------------------------------------------------------------- */
 
-  /*  Sign of value. */
+  //  Sign of value.
 
   int iexp = kexp;
   int isign = (iexp < 128) * 2 - 1;
 
   iexp -= iexp < 128 ? 0 : 128;
 
-  /*  Decode value. */
+  //  Decode value.
 
-  /* pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); */
+  // double pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64));
 
   iexp -= 64;
 
@@ -1968,7 +1973,7 @@ decfp2(int kexp, int kmant)
   /* ----------------------------------------------------------------- */
 
   return pval;
-} /* decfp2 */
+}
 #include <stdarg.h>
 #include <stdint.h>
 
@@ -2319,11 +2324,7 @@ gribPrintSec1(int *isec0, int *isec1)
   int ibit, ierr, iout, iyear;
   int jiloop;
   float value;
-
   char hversion[9];
-  /*
-  char hfirst[121], hsecond[121], hthird[121], hfourth[121];
-  */
 
   grsdef();
 
@@ -2347,22 +2348,6 @@ gribPrintSec1(int *isec0, int *isec1)
   fprintf(grprsm, " Flag (Code Table 1)                   %8.8d\n", iout);
   fprintf(grprsm, " Parameter identifier (Code Table 2). %9d\n", isec1[5]);
 
-  /*
-      IERR = CHKTAB2(ISEC1,HFIRST,HSECOND,HTHIRD,HFOURTH)
-      IF( IERR .EQ. 0 ) THEN
-       DO JLOOP = 121, 1, -1
-          IF( HSECOND(JLOOP:JLOOP).NE.' ' ) THEN
-            IOFFSET = JLOOP
-            GOTO 110
-          ENDIF
-        ENDDO
-        GOTO 120
- 110    CONTINUE
-        WRITE(*,'(2H ",A,1H")') HSECOND(1:IOFFSET)
- 120    CONTINUE
-      ENDIF
-  */
-
   if (isec1[5] != 127)
     {
       fprintf(grprsm, " Type of level (Code Table 3).        %9d\n", isec1[6]);
@@ -2379,7 +2364,6 @@ gribPrintSec1(int *isec0, int *isec1)
   if (iyear != 255)
     {
       int date, time;
-      /* iyear  = ((isec1[20]-1)*100 + isec1[9]); */
       gribDateTime(isec1, &date, &time);
       iyear = date / 10000;
       fprintf(grprsm, " Year of reference time of data.      %9d  (%4d)\n", isec1[9], iyear);
@@ -2408,10 +2392,10 @@ gribPrintSec1(int *isec0, int *isec1)
   else
     fprintf(grprsm, " Century of reference time of data.   %9d\n", isec1[20]);
 
-  /*   Print sub-centre  */
+  //   Print sub-centre
   fprintf(grprsm, " Sub-centre identifier.               %9d\n", ISEC1_SubCenterID);
 
-  /*   Decimal scale factor  */
+  //   Decimal scale factor
   fprintf(grprsm, " Units decimal scaling factor.        %9d\n", isec1[22]);
 
   /*
@@ -2473,7 +2457,7 @@ gribPrintSec1(int *isec0, int *isec1)
       fprintf(grprsm, " Class.                               %9d\n", isec1[37]);
       fprintf(grprsm, " Type.                                %9d\n", isec1[38]);
       fprintf(grprsm, " Stream.                              %9d\n", isec1[39]);
-      sprintf(hversion, "%4s", (char *) &isec1[40]);
+      snprintf(hversion, sizeof(hversion), "%4s", (char *) &isec1[40]);
       hversion[4] = 0;
       fprintf(grprsm, " Version number or Experiment identifier.  %4s\n", hversion);
       /*
@@ -2792,14 +2776,11 @@ gribPrintSec1(int *isec0, int *isec1)
           fprintf(grprsm, "   Type                               %9d\n", isec1[42]);
           fprintf(grprsm, "   Stream                             %9d\n", isec1[43]);
           /*
-          sprintf(hversion, "%8d", isec1[44]);
+          snprintf(hversion, sizeof(hversion), "%8d", isec1[44]);
           fprintf(grprsm, "   Version number/experiment identifier:   %4s\n", &hversion[4]);
           */
           iyear = isec1[45];
-          if (iyear > 50)
-            iyear = iyear + 1900;
-          else
-            iyear = iyear + 2000;
+          iyear = iyear + ((iyear > 50) ? 1900 : 2000);
 
           fprintf(grprsm, "   Year                               %9d\n", iyear);
           fprintf(grprsm, "   Month                              %9d\n", isec1[46]);
@@ -3020,11 +3001,7 @@ printQuasi(int *isec2)
   fprintf(grprsm, "  Number of points along a parallel varies.\n");
 
   int ntos = (fmod((double) isec2[10], 128.) < 64);
-
-  if (ntos)
-    fprintf(grprsm, "  Number of points.   Parallel. (North to South)\n");
-  else
-    fprintf(grprsm, "  Number of points.   Parallel. (South to North)\n");
+  fprintf(grprsm, "  Number of points.   Parallel. %s\n", ntos ? "(North to South)" : "(South to North)");
 
   // Display number of points for each latitude
   int latcnt = isec2[2];
@@ -3034,7 +3011,7 @@ printQuasi(int *isec2)
   for (int j = 0; j < latcnt; ++j)
     {
       nextlat = nextlat + 1;
-      sprintf(yout, "%4d", nextlat);
+      snprintf(yout, sizeof(yout), "%4d", nextlat);
 
       // Finished?
       if (nextlat > latcnt) break;
@@ -3055,7 +3032,7 @@ printQuasi(int *isec2)
           if (nextlat < latcnt) goto LABEL110;
         }
       // Display neighbouring latitudes with same number of points as 'nn to mm'.
-      if (nrepeat >= 1) sprintf(yout + 4, "to %5d", nextlat);
+      if (nrepeat >= 1) snprintf(yout + 4, sizeof(yout) - 4, "to %5d", nextlat);
       fprintf(grprsm, " %5d                %-12s\n", isec2[nextlat + 21], yout);
       memset(yout, ' ', (size_t) 11);
     }
@@ -3718,10 +3695,9 @@ gribCheckSeek(int fileID, long *offset, int *version)
 int
 gribFileSeek(int fileID, long *offset)
 {
-  /* position file pointer after GRIB */
+  // position file pointer after GRIB
   const long GRIB = 0x47524942;
   long code = 0;
-  int ch;
   int retry = 4096 * 4096;
 
   *offset = 0;
@@ -3730,7 +3706,7 @@ gribFileSeek(int fileID, long *offset)
 
   while (retry--)
     {
-      ch = filePtrGetc(fileptr);
+      int ch = filePtrGetc(fileptr);
       if (ch == EOF) return -1;
 
       code = ((code << 8) + ch) & 0xFFFFFFFF;
@@ -3892,10 +3868,7 @@ gribGetSize(int fileID)
       return 0;
     }
 
-  if (ierr == -1)
-    return 0;
-  else if (ierr == 1)
-    return 0;
+  if (ierr == -1) return 0;
 
   size_t recSize = gribReadSize(fileID);
 
@@ -3914,6 +3887,7 @@ gribRead(int fileID, void *buffer, size_t *buffersize)
   if (ierr > 0)
     {
       Warning("GRIB record not found!");
+      *buffersize = 0;
       return -2;
     }
 
@@ -3922,11 +3896,6 @@ gribRead(int fileID, void *buffer, size_t *buffersize)
       *buffersize = 0;
       return -1;
     }
-  else if (ierr == 1)
-    {
-      *buffersize = 0;
-      return -2;
-    }
 
   size_t recSize = gribReadSize(fileID);
   size_t readSize = recSize;
@@ -4060,9 +4029,7 @@ C     ----------------------------------------------------------------
   /*
     Common area variables have not been set. Set them.
   */
-  /*
-    Set GRIB calendar.
-  */
+  // Set GRIB calendar.
   if (CGRIBEX_grib_calendar == -1)
     {
       CGRIBEX_grib_calendar = CALENDAR_PROLEPTIC;
@@ -4084,18 +4051,14 @@ C     ----------------------------------------------------------------
             CGRIBEX_grib_calendar = CALENDAR_NONE;
         }
     }
-  /*
-    Set GRIBEX compatibility mode.
-  */
+  // Set GRIBEX compatibility mode.
   envString = getenv("GRIB_GRIBEX_MODE_ON");
   if (envString != NULL)
     {
       if (atoi(envString) == 1) CGRIBEX_Const = 0;
     }
 
-  /*
-    See if output stream needs changing
-  */
+  // See if output stream needs changing
   grprsm = stdout;
   env_stream = getenv("GRPRS_STREAM");
   if (env_stream)
@@ -4113,7 +4076,7 @@ C     ----------------------------------------------------------------
           else
             {
               char filename[] = "unit.00";
-              sprintf(filename, "%2.2d", unit);
+              snprintf(filename, sizeof(filename), "%2.2d", unit);
               grprsm = fopen(filename, "w");
               if (!grprsm) SysError("GRPRS_STREAM = %d", unit);
             }
@@ -4127,9 +4090,7 @@ C     ----------------------------------------------------------------
             }
         }
     }
-  /*
-    Mark common area values set by user.
-  */
+  // Mark common area values set by user.
   lfirst = false;
 }
 
@@ -5191,7 +5152,7 @@ grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *g
   printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf);
   */
   char paramstr[16];
-  sprintf(paramstr, "%d.%d.%d", paramnum, paramcat, dis);
+  snprintf(paramstr, sizeof(paramstr), "%d.%d.%d", paramnum, paramcat, dis);
   fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %-9s %7d : %5d %5d %6.4g\n", nrec, offset, recpos,
           recsize, GRIB_EDITION(is), ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len, paramstr, level1, level1type,
           gridtype, cr);
@@ -12614,7 +12575,7 @@ encode_dummy(void)
   (void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL);
   (void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL);
 }
-static const char grb_libvers[] = "2.3.0";
+static const char grb_libvers[] = "2.3.1";
 const char *
 cgribexLibraryVersion(void)
 {
diff --git a/src/grb_read.c b/src/grb_read.c
index 628f43b8b317cc16be5163e45aa1210c5b6e96d3..9c82461945d496e7b14a77979cd8bda2addf1717 100644
--- a/src/grb_read.c
+++ b/src/grb_read.c
@@ -309,7 +309,7 @@ grb_read_next_record(stream_t *streamptr, int recID, int memType, void *data, si
 }
 
 void
-grb_read_record(stream_t *streamptr, int memType, void *data, size_t *numMissVals)
+grb_read_field(stream_t *streamptr, int memType, void *data, size_t *numMissVals)
 {
   int tsID = streamptr->curTsID;
   int vrecID = streamptr->tsteps[tsID].curRecID;
diff --git a/src/grb_write.c b/src/grb_write.c
index f9c9ec8d02b344815bcca5ad83fb80f10e5dbfe0..9ece9e4c10669e5875cc02efa512ac4047b1c8d8 100644
--- a/src/grb_write.c
+++ b/src/grb_write.c
@@ -216,7 +216,7 @@ fillup_gribbuffer(size_t nbytes, unsigned char *gribbuffer)
 }
 
 void
-grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+grbCopyField(stream_t *streamptr2, stream_t *streamptr1)
 {
   int filetype = streamptr1->filetype;
   int fileID1 = streamptr1->fileID;
@@ -488,7 +488,7 @@ grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, siz
 }
 
 void
-grb_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals)
+grb_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals)
 {
   int varID = streamptr->record->varID;
   int levelID = streamptr->record->levelID;
diff --git a/src/stream.c b/src/stream.c
index 8ebd6be67f58a15144661505f6d1f7bed42bda93..81fee3cae624cb8f00ecfc238bb57ca3c65d0dcb 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -671,10 +671,17 @@ streamOpenID(const char *filename, char filemode, int filetype, int resH)
 #ifndef HAVE_NC4HDF5_THREADSAFE
   if (CDI_Threadsafe)
     {
-#ifndef HAVE_LIBPTHREAD
-      Error("CDI threadsafe failed, pthread support not compiled in!");
+#ifdef HAVE_LIBPTHREAD
+      if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C || filetype == CDI_FILETYPE_NCZARR)
+        streamptr->lockIO = true;
+#else
+      static bool lwarn = true;
+      if (lwarn)
+        {
+          lwarn = false;
+          Warning("CDI threadsafe failed, pthread support not compiled in!");
+        }
 #endif
-      if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C) streamptr->lockIO = true;
     }
 #endif
 
@@ -706,6 +713,42 @@ streamOpenID(const char *filename, char filemode, int filetype, int resH)
   return streamID;
 }
 
+int
+streamOpenNCMem(int ncidp, char mode)
+{
+  cdiInitialize();
+  stream_t *streamptr = stream_new_entry(CDI_UNDEFID);
+  int streamID = CDI_ESYSTEM;
+
+#ifdef HAVE_NETCDF4
+  streamID = streamptr->self;
+  if (streamID < 0) return CDI_ELIMIT;
+
+  size_t max_file_path_length = 128;
+  size_t actual_length = 0;
+  char *filename = (char *) malloc(sizeof(char) * max_file_path_length);
+
+  nc_inq_path(ncidp, &actual_length, filename);
+
+  streamptr->filename = strdup(filename);
+  streamptr->filemode = mode;
+  streamptr->filetype = CDI_FILETYPE_NC4;
+  streamptr->fileID = ncidp;
+
+  if (mode == 'r')
+    {
+      int status = stream_create_vlist(streamptr, NULL);
+      if (status < 0)
+        {
+          streamID = status;
+          if (streamptr->record) Free(streamptr->record);
+          reshRemove(streamptr->self, &streamOps);
+        }
+    }
+#endif
+
+  return streamID;
+}
 static int
 streamOpen(const char *filename, const char *filemode, int filetype)
 {
@@ -753,7 +796,7 @@ streamOpenA(const char *filename, const char *filemode, int filetype)
   if (str_is_equal(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID);
 
   {
-    void (*streamCloseDelegate)(stream_t * streamptr, int recordBufIsToBeDeleted)
+    void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
         = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func;
 
     streamCloseDelegate(streamptr, 0);
@@ -1222,14 +1265,10 @@ deallocate_sleveltable_t(sleveltable_t *entry)
 }
 
 static void
-streamDestroy(stream_t *streamptr)
+streamDestroyViaDelegate(stream_t *streamptr, void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted))
 {
-  xassert(streamptr);
-  int vlistID = streamptr->vlistID;
-
-  void (*streamCloseDelegate)(stream_t * streamptr, int recordBufIsToBeDeleted)
-      = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func;
 
+  xassert(streamptr);
   if (streamptr->filetype != CDI_FILETYPE_UNDEF) streamCloseDelegate(streamptr, 1);
 
   if (streamptr->record)
@@ -1285,6 +1324,7 @@ streamDestroy(stream_t *streamptr)
     }
 #endif
 
+  int vlistID = streamptr->vlistID;
   if (vlistID != -1)
     {
       int taxisID = (streamptr->filemode != 'w') ? vlistInqTaxis(vlistID) : -1;
@@ -1299,6 +1339,16 @@ streamDestroy(stream_t *streamptr)
   Free(streamptr);
 }
 
+
+static void
+streamDestroy(stream_t *streamptr)
+{
+  void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
+      = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func;
+
+  streamDestroyViaDelegate(streamptr, streamCloseDelegate);
+}
+
 static void
 streamDestroyP(void *streamptr)
 {
@@ -1390,7 +1440,7 @@ streamSync(int streamID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
-  void (*myStreamSync_)(stream_t * streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func;
+  void (*myStreamSync_)(stream_t *streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func;
   myStreamSync_(streamptr);
 }
 
@@ -1424,7 +1474,7 @@ cdiStreamDefTimestep_(stream_t *streamptr, int tsID)
       /* usually points to cdfDefTimestep in serial mode but
        * to cdiPioCdfDefTimestep on servers and to a null-op on
        * clients in client/server mode */
-      void (*myCdfDefTimestep)(stream_t * streamptr, int tsID, size_t)
+      void (*myCdfDefTimestep)(stream_t *streamptr, int tsID, size_t)
           = (void (*)(stream_t *, int, size_t)) namespaceSwitchGet(NSSWITCH_CDF_DEF_TIMESTEP).func;
       myCdfDefTimestep(streamptr, tsID, 1);
     }
@@ -1462,7 +1512,7 @@ streamDefTimestep(int streamID, int tsID)
 
   if (streamptr->lockIO) CDI_IO_LOCK();
 
-  int (*myStreamDefTimestep_)(stream_t * streamptr, int tsID)
+  int (*myStreamDefTimestep_)(stream_t *streamptr, int tsID)
       = (int (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_DEF_TIMESTEP_).func;
   int status = myStreamDefTimestep_(streamptr, tsID);
 
@@ -1763,7 +1813,7 @@ streamTxCode(void *s)
 void
 cdiStreamSetupVlist(stream_t *s, int vlistID)
 {
-  void (*myStreamSetupVlist)(stream_t * s, int vlistID)
+  void (*myStreamSetupVlist)(stream_t *s, int vlistID)
       = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func;
   myStreamSetupVlist(s, vlistID);
 }
@@ -1821,7 +1871,7 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID)
             /* calls cdfDefCoordinateVars in serial mode but
              * cdiPioClientStreamNOP (i.e. nothing) on client ranks
              * and cdiPioServerCdfDefVars on server ranks in parallel mode*/
-            void (*myCdfDefVars)(stream_t * streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
+            void (*myCdfDefVars)(stream_t *streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func;
             myCdfDefVars(streamptr);
           }
           break;
@@ -1989,6 +2039,64 @@ streamUnpack(char *unpackBuffer, int unpackBufferSize, int *unpackBufferPos, int
   return retval;
 }
 
+
+/* *
+ * This function does not really close the memio,
+ * this has to be done outside cdi to access the memory buffer*/
+void
+freePtrAfterNCMem(stream_t *streamptr, int recordBufIsToBeDeleted)
+{
+  int fileID = streamptr->fileID;
+
+  if (fileID == CDI_UNDEFID)
+    {
+      Warning("File %s not open!", streamptr->filename);
+      return;
+    }
+
+  if (streamptr->ntsteps == 0 && streamptr->tsteps != NULL)
+    {
+      if (streamptr->tsteps[0].records)
+        {
+          Free(streamptr->tsteps[0].records);
+          streamptr->tsteps[0].records = NULL;
+        }
+      if (streamptr->tsteps[0].recIDs)
+        {
+          Free(streamptr->tsteps[0].recIDs);
+          streamptr->tsteps[0].recIDs = NULL;
+        }
+    }
+}
+
+
+void
+streamCloseNCMem(int streamID)
+{
+  stream_t *streamptr = stream_to_pointer(streamID);
+
+  bool lockIO = streamptr->lockIO;
+  if (lockIO) CDI_IO_LOCK();
+
+  if (CDI_Debug) Message("streamID = %d filename = %s", streamID, streamptr->filename);
+  streamDestroyViaDelegate(streamptr,freePtrAfterNCMem);
+  reshRemove(streamID, &streamOps);
+  if (CDI_Debug) Message("Removed stream %d from stream list", streamID);
+
+  if (lockIO) CDI_IO_UNLOCK();
+}
+
+int
+streamOpenReadNCMem(int ncidp)
+{
+  return streamOpenNCMem(ncidp, 'r');
+}
+int
+streamOpenWriteNCMem(int ncidp)
+{
+  return streamOpenNCMem(ncidp, 'w');
+}
+
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/src/stream_cdf.h b/src/stream_cdf.h
index 0e0991c1d81507db6385c16a57a2048bf30fb6c5..d4b379742b09f9983910c0310f8c0220e3eac2e8 100644
--- a/src/stream_cdf.h
+++ b/src/stream_cdf.h
@@ -30,14 +30,14 @@ int cdfInqTimestep(stream_t *streamptr, int tsID);
 int cdfInqContents(stream_t *streamptr);
 
 void cdfEndDef(stream_t *streamptr);
-void cdfDefRecord(stream_t *streamptr);
+void cdfDefField(stream_t *streamptr);
 
 void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
 
 void cdfDefineAttributes(int filetype, int vlistID, int varID, int fileID, int ncvarID);
 
-void cdf_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
-void cdf_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals);
+void cdf_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
+void cdf_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals);
 
 void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, size_t *numMissVals);
 void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, size_t numMissVals);
diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c
index 7d9e9e9f25166d3ee1b6b16d7ae8d2cf10a58421..9b7565a012bdd95b2b93a32f63d07e6db6648768 100644
--- a/src/stream_cdf_i.c
+++ b/src/stream_cdf_i.c
@@ -55,6 +55,7 @@ typedef struct
   int ncid;
   int varStatus;
   bool ignoreVar;
+  bool isHealPIX;
   bool isCubeSphere;
   bool isCharAxis;
   bool isXaxis;
@@ -114,6 +115,7 @@ typedef struct
   size_t gridSize;
   size_t xSize;
   size_t ySize;
+  int nattsNC;
   int natts;
   int *atts;
   size_t vctsize;
@@ -189,15 +191,6 @@ scan_time_units(const char *unitstr)
   return timeunit;
 }
 
-static void
-set_forecast_time(const char *timestr, taxis_t *taxis)
-{
-  if (strlen(timestr) != 0)
-    taxis->fDateTime = scan_time_string(timestr);
-  else
-    cdiDateTime_init(&(taxis->fDateTime));
-}
-
 static int
 set_base_time(const char *timeUnitsStr, taxis_t *taxis)
 {
@@ -525,43 +518,46 @@ cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor)
 }
 
 static int
-cdf_time_dimid(int fileID, int ndims, int nvars, ncdim_t *ncdims)
+cdf_time_dimid(int fileID, int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars)
 {
   char dimname[CDI_MAX_NAME];
-
   for (int dimid = 0; dimid < ndims; ++dimid)
     {
-      dimname[0] = 0;
-      cdf_inq_dimname(fileID, ncdims[dimid].dimid, dimname);
-      if ((dimname[0] == 'T' || dimname[0] == 't') && dimname[1] == 'i' && dimname[2] == 'm' && dimname[3] == 'e') return dimid;
+      strcpy(dimname, ncdims[dimid].name);
+      if (str_is_equal("time", str_to_lower(dimname))) return dimid;
     }
 
+  bool check_dimids[MAX_DIMS_CDF];
+  for (int i = 0; i < MAX_DIMS_CDF; ++i) check_dimids[i] = false;
+
   for (int varid = 0; varid < nvars; ++varid)
     {
-      nc_type xtype;
-      int nvdims, nvatts, dimids[9];
-      cdf_inq_var(fileID, varid, NULL, &xtype, &nvdims, dimids, &nvatts);
-      for (int i = 0; i < nvdims; ++i)
-        for (int dimid = 0; dimid < ndims; ++dimid)
-          if (ncdims[dimid].dimid == dimids[i])
-            {
-              dimids[i] = dimid;
-              break;
-            }
-
-      if (nvdims == 1)
+      ncvar_t *ncvar = &ncvars[varid];
+      if (ncvars[varid].ndims == 1)
         {
-          char sbuf[CDI_MAX_NAME];
-          for (int iatt = 0; iatt < nvatts; ++iatt)
+          int dimid0 = CDI_UNDEFID;
+          for (int gdimid = 0; gdimid < ndims; ++gdimid)
+            if (ncdims[gdimid].dimid == ncvar->dimids[0])
+              {
+                dimid0 = gdimid;
+                break;
+              }
+
+          if (dimid0 != CDI_UNDEFID && check_dimids[dimid0] == false)
             {
-              sbuf[0] = 0;
-              cdf_inq_attname(fileID, varid, iatt, sbuf);
-              if (strStartsWith(sbuf, "units"))
-                {
-                  cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
-                  str_to_lower(sbuf);
+              if (ncdims[dimid0].ncvarid != CDI_UNDEFID && ncdims[dimid0].ncvarid != varid) continue;
+              check_dimids[dimid0] = true;
 
-                  if (is_time_units(sbuf)) return dimids[0];
+              char sbuf[CDI_MAX_NAME];
+              for (int iatt = 0; iatt < ncvar->nattsNC; ++iatt)
+                {
+                  sbuf[0] = 0;
+                  cdf_inq_attname(fileID, varid, iatt, sbuf);
+                  if (str_is_equal(sbuf, "units"))
+                    {
+                      cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf);
+                      if (is_time_units(str_to_lower(sbuf))) return dimid0;
+                    }
                 }
             }
         }
@@ -573,9 +569,9 @@ cdf_time_dimid(int fileID, int ndims, int nvars, ncdim_t *ncdims)
 static void
 init_ncdims(int ndims, ncdim_t *ncdims)
 {
-  for (int ncdimid = 0; ncdimid < ndims; ncdimid++)
+  for (int gdimid = 0; gdimid < ndims; gdimid++)
     {
-      ncdim_t *ncdim = &ncdims[ncdimid];
+      ncdim_t *ncdim = &ncdims[gdimid];
       ncdim->dimid = CDI_UNDEFID;
       ncdim->ncvarid = CDI_UNDEFID;
       ncdim->dimtype = CDI_UNDEFID;
@@ -587,12 +583,13 @@ init_ncdims(int ndims, ncdim_t *ncdims)
 static void
 init_ncvars(int nvars, ncvar_t *ncvars, int ncid)
 {
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
+      ncvar_t *ncvar = &ncvars[varid];
       ncvar->ncid = ncid;
       ncvar->varStatus = UndefVar;
       ncvar->ignoreVar = false;
+      ncvar->isHealPIX = false;
       ncvar->isCubeSphere = false;
       ncvar->isCharAxis = false;
       ncvar->isXaxis = false;
@@ -652,6 +649,7 @@ init_ncvars(int nvars, ncvar_t *ncvars, int ncid)
       ncvar->gridSize = 0;
       ncvar->xSize = 0;
       ncvar->ySize = 0;
+      ncvar->nattsNC = 0;
       ncvar->natts = 0;
       ncvar->atts = NULL;
       ncvar->vctsize = 0;
@@ -924,13 +922,13 @@ cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname)
 
   fprintf(stderr, "%s:\n", oname);
 
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      const ncvar_t *ncvar = &ncvars[ncvarid];
+      const ncvar_t *ncvar = &ncvars[varid];
       int ndim = 0;
-      if (ncvar->varStatus == DataVar)
+      if (ncvar->varStatus == DataVar || ncvar->varStatus == UndefVar)
         {
-          axis[ndim++] = 'v';
+          axis[ndim++] = (ncvar->varStatus == DataVar) ? 'v' : 'u';
           axis[ndim++] = ':';
           for (int i = 0; i < ncvar->ndims; i++)
             {
@@ -957,7 +955,7 @@ cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname)
 
       axis[ndim++] = 0;
 
-      fprintf(stderr, "%3d %3d  %-6s %s\n", ncvarid, ndim-3, axis, ncvar->name);
+      fprintf(stderr, "%3d %3d  %-6s %s\n", varid, ndim-3, axis, ncvar->name);
     }
   // clang-format on
 }
@@ -1079,109 +1077,178 @@ is_valid_coordinate(ncvar_t *ncvar)
   return status;
 }
 
-#if defined __GNUC__ || (__GNUC__ == 4 && __GNUC_MINOR__ == 9)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow"
-#endif
-
 static void
-cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timedimid, int modelID, int format)
+read_coordinates_vars(int ncid, char *attstring, ncvar_t *ncvar, ncvar_t *ncvars, int *nchecked_vars, char *checked_vars[],
+                      int max_check_vars)
 {
-  int nvdims, nvatts;
-  nc_type xtype, atttype;
-  size_t attlen;
-  char name[CDI_MAX_NAME];
-  char attname[CDI_MAX_NAME];
-  char attstring[8192];
-
-  int nchecked_vars = 0;
-  enum
-  {
-    max_check_vars = 9
-  };
-  char *checked_vars[max_check_vars];
-  for (int i = 0; i < max_check_vars; ++i) checked_vars[i] = NULL;
-
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  bool lstop = false;
+  for (int i = 0; i < MAX_COORDVARS && !lstop; i++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
-      int ncid = ncvar->ncid;
-      int *dimidsp = ncvar->dimids;
+      while (isspace((int) *attstring)) attstring++;
+      if (*attstring == 0) break;
+      char *varname = attstring;
+      while (!isspace((int) *attstring) && *attstring != 0) attstring++;
+      if (*attstring == 0) lstop = true;
+      if (*(attstring - 1) == ',') *(attstring - 1) = 0;
+      *attstring++ = 0;
 
-      cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
-      for (int i = 0; i < nvdims; ++i)
-        for (int dimid = 0; dimid < ndims; ++dimid)
-          if (ncdims[dimid].dimid == dimidsp[i])
+      int dimvarid;
+      int status = nc_inq_varid(ncid, varname, &dimvarid);
+      if (status == NC_NOERR)
+        {
+          if (is_valid_coordinate(&ncvars[dimvarid]))
             {
-              dimidsp[i] = dimid;
-              break;
+              cdf_set_var(&ncvars[dimvarid], CoordVar);
+              if (!CDI_Ignore_Att_Coordinates)
+                {
+                  ncvar->coordvarids[i] = dimvarid;
+                  ncvar->ncoordvars++;
+                }
             }
-      strcpy(ncvar->name, name);
+        }
+      else
+        {
+          if (!CDI_Ignore_Att_Coordinates) ncvar->ncoordvars++;
 
-      for (int ncdimid = 0; ncdimid < nvdims; ncdimid++) ncvar->dimtypes[ncdimid] = -1;
+          int k;
+          for (k = 0; k < *nchecked_vars; ++k)
+            if (str_is_equal(checked_vars[k], varname)) break;
 
-      ncvar->xtype = xtype;
-      ncvar->ndims = nvdims;
+          if (k == *nchecked_vars)
+            {
+              if (*nchecked_vars < max_check_vars) checked_vars[*nchecked_vars++] = strdup(varname);
+              Warning("%s - >%s<", nc_strerror(status), varname);
+            }
+        }
+    }
+}
 
-#ifdef HAVE_NETCDF4
-      if (format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4)
+static void
+read_auxiliary_vars(int ncid, char *attstring, ncvar_t *ncvar, ncvar_t *ncvars)
+{
+  bool lstop = false;
+  for (int i = 0; i < MAX_AUXVARS && !lstop; i++)
+    {
+      while (isspace((int) *attstring)) attstring++;
+      if (*attstring == 0) break;
+      char *varname = attstring;
+      while (!isspace((int) *attstring) && *attstring != 0) attstring++;
+      if (*attstring == 0) lstop = true;
+      *attstring++ = 0;
+
+      int dimvarid;
+      int status = nc_inq_varid(ncid, varname, &dimvarid);
+      if (status == NC_NOERR)
         {
-          int shuffle = 0, deflate = 0, deflateLevel = 0;
-          nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflateLevel);
-          if (deflate > 0) ncvar->hasDeflate = true;
+          cdf_set_var(&ncvars[dimvarid], CoordVar);
+          //  if ( !CDI_Ignore_Att_Coordinates )
+          {
+            ncvar->auxvarids[i] = dimvarid;
+            ncvar->nauxvars++;
+          }
+        }
+      else
+        Warning("%s - %s", nc_strerror(status), varname);
+    }
+}
+
+static void
+set_vars_chunks(int ncid, int ncvarid, int nvdims, ncvar_t *ncvar)
+{
+  int shuffle = 0, deflate = 0, deflateLevel = 0;
+  nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflateLevel);
+  if (deflate > 0) ncvar->hasDeflate = true;
 
 #ifdef HAVE_NC_DEF_VAR_SZIP
-          int options_mask = 0, pixels_per_block = 0;
-          nc_inq_var_szip(ncid, ncvarid, &options_mask, &pixels_per_block);
-          if (options_mask && pixels_per_block) ncvar->hasSzip = true;
+  int options_mask = 0, pixels_per_block = 0;
+  nc_inq_var_szip(ncid, ncvarid, &options_mask, &pixels_per_block);
+  if (options_mask && pixels_per_block) ncvar->hasSzip = true;
 #endif
-          ncvar->hasFilter = cdf_get_var_filter(ncid, ncvarid, ncvar->filterSpec, CDI_MAX_NAME);
-          // if (ncvar->hasFilter) printf("filterSpec: %s=%s\n", ncvar->name, ncvar->filterSpec);
+  ncvar->hasFilter = cdf_get_var_filter(ncid, ncvarid, ncvar->filterSpec, CDI_MAX_NAME);
+  // if (ncvar->hasFilter) printf("filterSpec: %s=%s\n", ncvar->name, ncvar->filterSpec);
 
-          size_t chunks[nvdims];
-          int storageIn;
-          if (nc_inq_var_chunking(ncid, ncvarid, &storageIn, chunks) == NC_NOERR)
+  size_t chunks[nvdims];
+  int storageIn;
+  if (nc_inq_var_chunking(ncid, ncvarid, &storageIn, chunks) == NC_NOERR)
+    {
+      if (storageIn == NC_CHUNKED)
+        {
+          ncvar->isChunked = true;
+          for (int i = 0; i < nvdims; ++i) ncvar->chunks[i] = chunks[i];
+          if (CDI_Debug)
             {
-              if (storageIn == NC_CHUNKED)
-                {
-                  ncvar->isChunked = true;
-                  for (int i = 0; i < nvdims; ++i) ncvar->chunks[i] = chunks[i];
-                  if (CDI_Debug)
-                    {
-                      fprintf(stderr, "%s: chunking %d %d %d  chunks ", name, storageIn, NC_CONTIGUOUS, NC_CHUNKED);
-                      for (int i = 0; i < nvdims; ++i) fprintf(stderr, "%zu ", chunks[i]);
-                      fprintf(stderr, "\n");
-                    }
-
-                  set_extra_attr(ncvar->extra, nvdims, chunks);
-                }
+              fprintf(stderr, "%s: chunking %d %d %d  chunks ", ncvar->name, storageIn, NC_CONTIGUOUS, NC_CHUNKED);
+              for (int i = 0; i < nvdims; ++i) fprintf(stderr, "%zu ", chunks[i]);
+              fprintf(stderr, "\n");
             }
 
-          size_t size;
-          size_t nelems;
-          float preemption;
-          if (nc_get_var_chunk_cache(ncid, ncvarid, &size, &nelems, &preemption) == NC_NOERR)
+          set_extra_attr(ncvar->extra, nvdims, chunks);
+        }
+    }
+
+  size_t size;
+  size_t nelems;
+  float preemption;
+  if (nc_get_var_chunk_cache(ncid, ncvarid, &size, &nelems, &preemption) == NC_NOERR)
+    {
+      ncvar->chunkCacheSize = size;
+      ncvar->chunkCacheNelems = nelems;
+      ncvar->chunkCachePreemption = preemption;
+      if (CDI_Debug) fprintf(stderr, "%s: chunkCacheSize=%zu nelems=%zu preemption=%g\n", ncvar->name, size, nelems, preemption);
+    }
+}
+
+#if defined __GNUC__ || (__GNUC__ == 4 && __GNUC_MINOR__ == 9)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wstrict-overflow"
+#endif
+
+static void
+read_vars_info(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int format)
+{
+  for (int varid = 0; varid < nvars; varid++)
+    {
+      ncvar_t *ncvar = &ncvars[varid];
+      cdf_inq_var(ncvar->ncid, varid, ncvar->name, &ncvar->xtype, &ncvar->ndims, ncvar->dimids, &ncvar->nattsNC);
+
+      for (int vdimid = 0; vdimid < ncvar->ndims; ++vdimid)
+        for (int gdimid = 0; gdimid < ndims; ++gdimid)
+          if (ncdims[gdimid].dimid == ncvar->dimids[vdimid])
             {
-              ncvar->chunkCacheSize = size;
-              ncvar->chunkCacheNelems = nelems;
-              ncvar->chunkCachePreemption = preemption;
-              if (CDI_Debug) fprintf(stderr, "%s: chunkCacheSize=%zu nelems=%zu preemption=%g\n", name, size, nelems, preemption);
+              ncvar->dimids[vdimid] = gdimid;
+              break;
             }
+
+      for (int vdimid = 0; vdimid < ncvar->ndims; vdimid++) ncvar->dimtypes[vdimid] = -1;
+
+#ifdef HAVE_NETCDF4
+      if (format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4)
+        {
+          set_vars_chunks(ncvar->ncid, varid, ncvar->ndims, ncvar);
         }
 #endif
+    }
+}
 
-      if (nvdims > 0)
+static void
+set_vars_timetype(int nvars, ncvar_t *ncvars, int timedimid)
+{
+  for (int varid = 0; varid < nvars; varid++)
+    {
+      ncvar_t *ncvar = &ncvars[varid];
+      if (ncvar->ndims > 0)
         {
-          if (timedimid == dimidsp[0])
+          if (timedimid == ncvar->dimids[0])
             {
               ncvar->timetype = TIME_VARYING;
               cdf_set_dim(ncvar, 0, T_AXIS);
             }
           else
             {
-              for (int ncdimid = 1; ncdimid < nvdims; ncdimid++)
+              int nvdims = ncvar->ndims;
+              for (int vdimid = 1; vdimid < nvdims; vdimid++)
                 {
-                  if (timedimid == dimidsp[ncdimid])
+                  if (timedimid == ncvar->dimids[vdimid])
                     {
                       Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvar->name);
                       ncvar->varStatus = CoordVar;
@@ -1190,14 +1257,30 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed
             }
         }
     }
+}
+
+static void
+scan_vars_attr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int modelID)
+{
+  int nchecked_vars = 0;
+  enum
+  {
+    max_check_vars = 9
+  };
+  char *checked_vars[max_check_vars];
+  for (int i = 0; i < max_check_vars; ++i) checked_vars[i] = NULL;
+
+  char attname[CDI_MAX_NAME];
+  char attstring[8192];
 
   for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
     {
       ncvar_t *ncvar = &ncvars[ncvarid];
       int ncid = ncvar->ncid;
-      int *dimidsp = ncvar->dimids;
-
-      cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts);
+      const char *name = ncvar->name;
+      int nvdims = ncvar->ndims;
+      nc_type xtype = ncvar->xtype;
+      int nvatts = ncvar->nattsNC;
 
       if (ncvar->natts == 0 && nvatts > 0) ncvar->atts = (int *) Malloc((size_t) nvatts * sizeof(int));
 
@@ -1205,6 +1288,8 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed
         {
           int nc_cell_id = CDI_UNDEFID;
 
+          nc_type atttype;
+          size_t attlen;
           cdf_inq_attname(ncid, ncvarid, iatt, attname);
           cdf_inq_atttype(ncid, ncvarid, attname, &atttype);
           cdf_inq_attlen(ncid, ncvarid, attname, &attlen);
@@ -1387,82 +1472,12 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed
             }
           else if (isText && (str_is_equal(attname, "associate") || str_is_equal(attname, "coordinates")))
             {
-              bool lstop = false;
-              char *pstring = attstring;
-
-              for (int i = 0; i < MAX_COORDVARS && !lstop; i++)
-                {
-                  while (isspace((int) *pstring)) pstring++;
-                  if (*pstring == 0) break;
-                  char *varname = pstring;
-                  while (!isspace((int) *pstring) && *pstring != 0) pstring++;
-                  if (*pstring == 0) lstop = true;
-                  if (*(pstring - 1) == ',') *(pstring - 1) = 0;
-                  *pstring++ = 0;
-
-                  int dimvarid;
-                  int status = nc_inq_varid(ncid, varname, &dimvarid);
-                  if (status == NC_NOERR)
-                    {
-                      if (is_valid_coordinate(&ncvars[dimvarid]))
-                        {
-                          cdf_set_var(&ncvars[dimvarid], CoordVar);
-                          if (!CDI_Ignore_Att_Coordinates)
-                            {
-                              ncvar->coordvarids[i] = dimvarid;
-                              ncvar->ncoordvars++;
-                            }
-                        }
-                    }
-                  else
-                    {
-                      if (!CDI_Ignore_Att_Coordinates) ncvar->ncoordvars++;
-
-                      int k;
-                      for (k = 0; k < nchecked_vars; ++k)
-                        if (str_is_equal(checked_vars[k], varname)) break;
-
-                      if (k == nchecked_vars)
-                        {
-                          if (nchecked_vars < max_check_vars) checked_vars[nchecked_vars++] = strdup(varname);
-                          Warning("%s - >%s<", nc_strerror(status), varname);
-                        }
-                    }
-                }
-
+              read_coordinates_vars(ncid, attstring, ncvar, ncvars, &nchecked_vars, checked_vars, max_check_vars);
               cdf_set_var(ncvar, DataVar);
             }
           else if (isText && str_is_equal(attname, "auxiliary_variable"))
             {
-              bool lstop = false;
-              char *pstring = attstring;
-
-              for (int i = 0; i < MAX_AUXVARS; i++)
-                {
-                  while (isspace((int) *pstring)) pstring++;
-                  if (*pstring == 0) break;
-                  char *varname = pstring;
-                  while (!isspace((int) *pstring) && *pstring != 0) pstring++;
-                  if (*pstring == 0) lstop = true;
-                  *pstring++ = 0;
-
-                  int dimvarid;
-                  int status = nc_inq_varid(ncid, varname, &dimvarid);
-                  if (status == NC_NOERR)
-                    {
-                      cdf_set_var(&ncvars[dimvarid], CoordVar);
-                      //  if ( !CDI_Ignore_Att_Coordinates )
-                      {
-                        ncvar->auxvarids[i] = dimvarid;
-                        ncvar->nauxvars++;
-                      }
-                    }
-                  else
-                    Warning("%s - %s", nc_strerror(status), varname);
-
-                  if (lstop) break;
-                }
-
+              read_auxiliary_vars(ncid, attstring, ncvar, ncvars);
               cdf_set_var(ncvar, DataVar);
             }
           else if (isText && str_is_equal(attname, "grid_mapping"))
@@ -1473,6 +1488,14 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed
                 {
                   ncvar->gmapid = nc_gmap_id;
                   cdf_set_var(&ncvars[ncvar->gmapid], CoordVar);
+                  int nc_gmap_varid = ncvars[ncvar->gmapid].ncid;
+                  if (cdfCheckAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name"))
+                    {
+                      char gridMappingName[CDI_MAX_NAME];
+                      cdfGetAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name", CDI_MAX_NAME, gridMappingName);
+                      // if (str_is_equal(gridMappingName, "healpix")) ncvars[ncvar->gmapid].isHealPIX = true;
+                      if (str_is_equal(gridMappingName, "healpix")) ncvar->isHealPIX = true;
+                    }
                 }
               else
                 Warning("%s - %s", nc_strerror(status), attstring);
@@ -1482,22 +1505,26 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed
           else if (isText && str_is_equal(attname, "positive"))
             {
               str_to_lower(attstring);
-
               if (str_is_equal(attstring, "down"))
                 ncvar->positive = POSITIVE_DOWN;
               else if (str_is_equal(attstring, "up"))
                 ncvar->positive = POSITIVE_UP;
 
-              if (ncvar->ndims == 1)
-                {
-                  cdf_set_var(ncvar, CoordVar);
-                  cdf_set_dim(ncvar, 0, Z_AXIS);
-                  ncdims[ncvar->dimids[0]].dimtype = Z_AXIS;
-                }
-              else if (ncvar->ndims == 0)
+              int dimid0 = ncvar->dimids[0];
+              if (ncvar->varStatus == UndefVar
+                  && (nvdims == 0 || (nvdims == 1 && ncvar->dimtypes[0] == CDI_UNDEFID && ncdims[dimid0].ncvarid == CDI_UNDEFID)))
                 {
-                  cdf_set_var(ncvar, CoordVar);
-                  ncvar->isZaxis = true;
+                  if (nvdims == 1)
+                    {
+                      cdf_set_var(ncvar, CoordVar);
+                      cdf_set_dim(ncvar, 0, Z_AXIS);
+                      if (dimid0 < ndims) ncdims[dimid0].dimtype = Z_AXIS;
+                    }
+                  else if (nvdims == 0)
+                    {
+                      cdf_set_var(ncvar, CoordVar);
+                      ncvar->isZaxis = true;
+                    }
                 }
               else
                 {
@@ -1638,7 +1665,7 @@ cdf_set_chunk_info(stream_t *streamptr, int nvars, ncvar_t *ncvars)
 }
 
 static void
-cdfVerifyVarAttr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
+verify_vars_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 {
   nc_type atttype;
   size_t attlen;
@@ -1685,12 +1712,37 @@ cdfVerifyVarAttr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
     }
 }
 
+static void
+find_dimtypes(ncvar_t *ncvars, ncvar_t *ncvar, bool *plxdim, bool *plydim, bool *plzdim, int *plcdim)
+{
+  bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */;
+  int lcdim = 0;
+  int ndims = ncvar->ndims;
+  for (int i = 0; i < ndims; i++)
+    {
+      int dimtype = ncvar->dimtypes[i];
+      lxdim |= (dimtype == X_AXIS);
+      lydim |= (dimtype == Y_AXIS);
+      lzdim |= (dimtype == Z_AXIS);
+      if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
+      // ltdim |= (dimtype == T_AXIS);
+    }
+
+  if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
+  if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+
+  *plxdim = lxdim;
+  *plydim = lydim;
+  *plzdim = lzdim;
+  *plcdim = lcdim;
+}
+
 static void
 cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 {
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
+      ncvar_t *ncvar = &ncvars[varid];
       if (ncvar->varStatus == DataVar)
         {
           int ndims = ncvar->ndims;
@@ -1703,35 +1755,23 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 
           if (CDI_Debug)
             {
-              Message("var %d %s", ncvarid, ncvar->name);
+              Message("var %d %s", varid, ncvar->name);
               for (int i = 0; i < ndims; i++) printf("  dim%d type=%d  ", i, ncvar->dimtypes[i]);
               printf("\n");
             }
         }
     }
 
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
+      ncvar_t *ncvar = &ncvars[varid];
       if (ncvar->varStatus == DataVar)
         {
           bool lxdim = false, lydim = false, lzdim = false /* , ltdim = false */;
-          int lcdim = 0;
-          int ndims = ncvar->ndims;
-          for (int i = 0; i < ndims; i++)
-            {
-              int dimtype = ncvar->dimtypes[i];
-              lxdim |= (dimtype == X_AXIS);
-              lydim |= (dimtype == Y_AXIS);
-              lzdim |= (dimtype == Z_AXIS);
-              if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
-              // ltdim |= (dimtype == T_AXIS);
-            }
-
+          int lcdim;
+          find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim);
           int allcdims = lcdim;
-
-          if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
-          if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+          int ndims = ncvar->ndims;
 
           if (lxdim && (lydim || ncvar->gridtype == GRID_UNSTRUCTURED))
             for (int i = ndims - 1; i >= 0; i--)
@@ -1754,9 +1794,9 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
         }
     }
 
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
+      ncvar_t *ncvar = &ncvars[varid];
       int ndims = ncvar->ndims;
       for (int i = 0; i < ndims; i++)
         {
@@ -1772,28 +1812,16 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
         }
     }
 
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+  for (int varid = 0; varid < nvars; varid++)
     {
-      ncvar_t *ncvar = &ncvars[ncvarid];
+      ncvar_t *ncvar = &ncvars[varid];
       if (ncvar->varStatus == DataVar)
         {
           bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */;
           int lcdim = 0;
-          int ndims = ncvar->ndims;
-          for (int i = 0; i < ndims; i++)
-            {
-              int dimtype = ncvar->dimtypes[i];
-              lxdim |= (dimtype == X_AXIS);
-              lydim |= (dimtype == Y_AXIS);
-              lzdim |= (dimtype == Z_AXIS);
-              if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++;
-              // ltdim |= (dimtype == T_AXIS);
-            }
-
+          find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim);
           int allcdims = lcdim;
-
-          if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true;
-          if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true;
+          int ndims = ncvar->ndims;
 
           //   if ( ndims > 1 )
           for (int i = ndims - 1; i >= 0; i--)
@@ -1812,7 +1840,7 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
                       dimtype = X_AXIS;
                       lxdim = true;
                     }
-                  else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED)
+                  else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED && ncvar->isHealPIX == false)
                     // else if ( !lydim && ! (ncvars[ncvar->xvarid].dimids[0] == ncvars[ncvar->yvarid].dimids[0] &&
                     //                        ncvars[ncvar->xvarid].ndims == 1 && ncvars[ncvar->yvarid].ndims == 1))
                     {
@@ -2058,19 +2086,21 @@ grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
   if (ncvar->isChunked)
     {
       int ndims = ncvar->ndims;
+      size_t chunkSizeAllDims = 1;
+      for (int i = 0; i < ndims; ++i) chunkSizeAllDims *= ncvar->chunks[i];
 
+      size_t dimN = ncvar->chunks[ndims - 1];
       if (grid->type == GRID_UNSTRUCTURED)
         {
-          size_t chunkSize = ncvar->chunks[ndims - 1];
+          size_t chunkSize = (chunkSizeAllDims == dimN) ? dimN : 0;
           ncvar->chunkType = (chunkSize == grid->size) ? CDI_CHUNK_GRID : CDI_CHUNK_AUTO;
           if (ncvar->chunkType == CDI_CHUNK_AUTO && chunkSize > 1) ncvar->chunkSize = (int) chunkSize;
         }
       else
         {
-          if (grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && grid->x.size == ncvar->chunks[ndims - 1]
-              && grid->y.size == ncvar->chunks[ndims - 2])
+          if (grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && grid->x.size == dimN && grid->y.size == ncvar->chunks[ndims - 2])
             ncvar->chunkType = CDI_CHUNK_GRID;
-          else if (grid->x.size > 1 && grid->x.size == ncvar->chunks[ndims - 1])
+          else if (grid->x.size > 1 && grid->x.size == dimN && chunkSizeAllDims == dimN)
             ncvar->chunkType = CDI_CHUNK_LINES;
           else
             ncvar->chunkType = CDI_CHUNK_AUTO;
@@ -3739,7 +3769,7 @@ cdf_copy_attflt(int fileID, int vlistID, nc_type xtype, size_t attlen, char *att
   if (attlen > 8) Free(pattflt);
 }
 
-static bool
+static void
 check_cube_sphere(int vlistID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 {
   bool isGeosData = false;
@@ -3821,7 +3851,7 @@ check_cube_sphere(int vlistID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
         }
     }
 
-  return isGeosData;
+  if (CDI_Debug) Message("isGeosData %d", isGeosData);
 }
 
 static void
@@ -3885,12 +3915,6 @@ cdf_scan_global_attr(int fileID, int vlistID, int ngatts, int *instID, int *mode
               else if (str_is_equal(attname, "CDO"))
                 {
                 }
-              /*
-              else if ( str_is_equal(attname, "forecast_reference_time") )
-                {
-                  memcpy(fcreftime, attstring, attstrlen+1);
-                }
-              */
               else if (str_is_equal(attname, "grid_file_uri"))
                 {
                   memcpy(gridInfo->gridfile, attstring, attstrlen + 1);
@@ -4259,7 +4283,7 @@ cdfVerifyVars(int nvars, ncvar_t *ncvars
 }
 
 static CdiDateTime
-wrf_read_timestep(int fileID, int nctimevarid, int tsID)
+wrf_read_timestep(int fileID, int nctimevarid, size_t tsID)
 {
   enum
   {
@@ -4267,7 +4291,7 @@ wrf_read_timestep(int fileID, int nctimevarid, int tsID)
     dateTimeSepPos = 19,
     dateTimeStrSize = 128,
   };
-  size_t start[2] = { (size_t) tsID, 0 }, count[2] = { 1, dateTimeSepPos };
+  size_t start[2] = { tsID, 0 }, count[2] = { 1, dateTimeSepPos };
   char stvalue[dateTimeStrSize];
   stvalue[0] = 0;
   cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue);
@@ -4313,7 +4337,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
       int fileID = streamptr->fileID;
       int nctimevarid = streamptr->basetime.ncvarid;
       int nctimeboundsid = streamptr->basetime.ncvarboundsid;
-      bool hasTimesteps = (nctimevarid != CDI_UNDEFID && streamptr->basetime.hasUnits);
+      bool hasTimesteps = (nctimevarid != CDI_UNDEFID /*&& streamptr->basetime.hasUnits*/);
 
       int *ncStepIndices = (int *) Malloc(numTimesteps * sizeof(int));
       for (size_t tsID = 0; tsID < numTimesteps; ++tsID) ncStepIndices[tsID] = (int) tsID;
@@ -4326,10 +4350,9 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
 
           if (streamptr->basetime.isWRF)
             {
-              for (size_t tsID = 0; tsID < numTimesteps; ++tsID)
-                vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, (int) tsID);
+              for (size_t tsID = 0; tsID < numTimesteps; ++tsID) vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, tsID);
             }
-          else
+          else if (streamptr->basetime.hasUnits)
             {
               double *timevarBuffer = (double *) Malloc(numTimesteps * sizeof(double));
               cdf_get_var_double(fileID, nctimevarid, timevarBuffer);
@@ -4337,6 +4360,10 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
                 vDateTimeList[tsID] = cdi_decode_timeval(get_timevalue(fileID, nctimevarid, tsID, timevarBuffer), taxis0);
               if (timevarBuffer) Free(timevarBuffer);
             }
+          else
+            {
+              hasTimesteps = false;
+            }
         }
 
       // process query information if available
@@ -4372,6 +4399,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
         }
 
       if (ncStepIndices) Free(ncStepIndices);
+      if (vDateTimeList) Free(vDateTimeList);
 
       if (hasTimesteps)
         {
@@ -4410,8 +4438,6 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0)
                 }
             }
         }
-
-      if (vDateTimeList) Free(vDateTimeList);
     }
 }
 
@@ -4424,82 +4450,155 @@ stream_set_ncdims(stream_t *streamptr, int ndims, ncdim_t *ncdims)
   for (int i = 0; i < n; i++) streamptr->ncDimLen[i] = ncdims[i].len;
 }
 
+static void
+set_ncdim_ids(int fileID, int ndims, ncdim_t *ncdims)
+{
+  if (ndims)
+    {
+      int gdimid = 0;
+      for (int i = 0; i < NC_MAX_DIMS; ++i)
+        {
+          if (nc_inq_dimlen(fileID, i, NULL) == NC_NOERR)
+            {
+              ncdims[gdimid++].dimid = i;
+              if (gdimid == ndims) break;
+            }
+        }
+    }
+}
+
+static void
+read_ncdims(int fileID, int ndims, ncdim_t *ncdims)
+{
+  for (int gdimid = 0; gdimid < ndims; gdimid++)
+    {
+      cdf_inq_dimlen(fileID, ncdims[gdimid].dimid, &ncdims[gdimid].len);
+      cdf_inq_dimname(fileID, ncdims[gdimid].dimid, ncdims[gdimid].name);
+    }
+}
+
+static void
+check_ncgroups(int fileID)
+{
+  int numgrps = 0;
+  int ncids[NC_MAX_VARS];
+  char gname[CDI_MAX_NAME];
+  nc_inq_grps(fileID, &numgrps, ncids);
+  for (int i = 0; i < numgrps; ++i)
+    {
+      int ncid = ncids[i];
+      nc_inq_grpname(ncid, gname);
+      int gndims, gnvars, gngatts, gunlimdimid;
+      cdf_inq(ncid, &gndims, &gnvars, &gngatts, &gunlimdimid);
+
+      if (CDI_Debug) Message("%s: ndims %d, nvars %d, ngatts %d", gname, gndims, gnvars, gngatts);
+    }
+  if (numgrps) Warning("NetCDF4 groups not supported! Found %d root group%s.", numgrps, (numgrps > 1) ? "s" : "");
+}
+
+static void
+find_coordinates_vars(int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars)
+{
+  for (int gdimid = 0; gdimid < ndims; gdimid++)
+    {
+      for (int varid = 0; varid < nvars; varid++)
+        {
+          ncvar_t *ncvar = &ncvars[varid];
+          if (ncvar->ndims == 1 && gdimid == ncvar->dimids[0] && ncdims[gdimid].ncvarid == CDI_UNDEFID)
+            {
+              if (str_is_equal(ncvar->name, ncdims[gdimid].name))
+                {
+                  ncdims[gdimid].ncvarid = varid;
+                  ncvar->varStatus = CoordVar;
+                }
+            }
+        }
+    }
+}
+
+// set time dependent data vars
+static void
+find_varying_data_vars1d(int timedimid, int nvars, ncvar_t *ncvars)
+{
+  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
+    {
+      ncvar_t *ncvar = &ncvars[ncvarid];
+      if (ncvar->ndims == 1)
+        {
+          if (timedimid != CDI_UNDEFID && timedimid == ncvar->dimids[0])
+            {
+              if (ncvar->varStatus != CoordVar) cdf_set_var(ncvar, DataVar);
+            }
+          else
+            {
+              //  if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar);
+            }
+          // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar);
+        }
+    }
+}
+
+static void
+set_coordinates_varids(int nvars, ncvar_t *ncvars)
+{
+  for (int varid = 0; varid < nvars; varid++)
+    {
+      ncvar_t *ncvar = &ncvars[varid];
+      if (ncvar->varStatus == DataVar && ncvar->ncoordvars)
+        {
+          for (int i = 0; i < ncvar->ncoordvars; i++)
+            {
+              int ncvaridc = ncvar->coordvarids[i];
+              if (ncvaridc != CDI_UNDEFID)
+                {
+                  ncvar_t *ncvarc = &ncvars[ncvaridc];
+                  // clang-format off
+                  if      (ncvarc->isLon || ncvarc->isXaxis) ncvar->xvarid = ncvaridc;
+                  else if (ncvarc->isLat || ncvarc->isYaxis) ncvar->yvarid = ncvaridc;
+                  else if (ncvarc->isZaxis)                  ncvar->zvarid = ncvaridc;
+                  else if (ncvarc->isTaxis)                  ncvar->tvarid = ncvaridc;
+                  else if (ncvarc->isCharAxis)               ncvar->cvarids[i] = ncvaridc;
+                  else if (ncvarc->printWarning)
+                    {
+                      Warning("Coordinates variable %s can't be assigned!", ncvarc->name);
+                      ncvarc->printWarning = false;
+                    }
+                  // clang-format on
+                }
+            }
+        }
+    }
+}
+
 int
 cdfInqContents(stream_t *streamptr)
 {
-  bool timeHasUnits = false;
-  bool timeHasBounds = false;
-  bool timeClimatology = false;
-  int leadtime_id = CDI_UNDEFID;
-  int format = 0;
-  char fcreftime[CDI_MAX_NAME];
   GridInfo gridInfo;
   gridInfo.gridfile[0] = 0;
   memset(gridInfo.uuid, 0, CDI_UUID_SIZE);
   gridInfo.number_of_grid_used = CDI_UNDEFID;
   gridInfo.timedimid = CDI_UNDEFID;
 
-  fcreftime[0] = 0;
-
   int vlistID = streamptr->vlistID;
   int fileID = streamptr->fileID;
 
   if (CDI_Debug) Message("streamID = %d, fileID = %d", streamptr->self, fileID);
 
-#ifdef HAVE_NETCDF4
-  nc_inq_format(fileID, &format);
-#endif
-
   int ndims = 0, nvars = 0, ngatts = 0, unlimdimid = 0;
   cdf_inq(fileID, &ndims, &nvars, &ngatts, &unlimdimid);
 
   if (CDI_Debug) Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts);
-  /*
-  if ( ndims == 0 )
-    {
-      Warning("No dimensions found!");
-      return CDI_EUFSTRUCT;
-    }
-  */
+
   // alloc ncdims
   ncdim_t *ncdims = ndims ? (ncdim_t *) Malloc((size_t) ndims * sizeof(ncdim_t)) : NULL;
   init_ncdims(ndims, ncdims);
+  set_ncdim_ids(fileID, ndims, ncdims);
+  read_ncdims(fileID, ndims, ncdims);
 
-  if (ndims)
-    {
-      int ncdimid = 0;
-      for (int dimid = 0; dimid < NC_MAX_DIMS; ++dimid)
-        {
-          if (nc_inq_dimlen(fileID, dimid, NULL) == NC_NOERR)
-            {
-              ncdims[ncdimid++].dimid = dimid;
-              if (ncdimid == ndims) break;
-            }
-        }
-    }
-
+  int format = 0;
 #ifdef HAVE_NETCDF4
-  if (format == NC_FORMAT_NETCDF4)
-    {
-      int numgrps = 0;
-      int ncids[NC_MAX_VARS];
-      char gname[CDI_MAX_NAME];
-      nc_inq_grps(fileID, &numgrps, ncids);
-      for (int i = 0; i < numgrps; ++i)
-        {
-          int ncid = ncids[i];
-          nc_inq_grpname(ncid, gname);
-          int gndims, gnvars, gngatts, gunlimdimid;
-          cdf_inq(ncid, &gndims, &gnvars, &gngatts, &gunlimdimid);
-
-          if (CDI_Debug) Message("%s: ndims %d, nvars %d, ngatts %d", gname, gndims, gnvars, gngatts);
-
-          if (gndims == 0)
-            {
-            }
-        }
-      if (numgrps) Warning("NetCDF4 groups not supported! Found %d root group%s.", numgrps, (numgrps > 1) ? "s" : "");
-    }
+  nc_inq_format(fileID, &format);
+  if (format == NC_FORMAT_NETCDF4) check_ncgroups(fileID);
 #endif
 
   if (nvars == 0)
@@ -4512,6 +4611,9 @@ cdfInqContents(stream_t *streamptr)
   ncvar_t *ncvars = (ncvar_t *) Malloc((size_t) nvars * sizeof(ncvar_t));
   init_ncvars(nvars, ncvars, fileID);
 
+  read_vars_info(nvars, ncvars, ndims, ncdims, format);
+  find_coordinates_vars(ndims, ncdims, nvars, ncvars);
+
   // scan global attributes
   int instID = CDI_UNDEFID;
   int modelID = CDI_UNDEFID;
@@ -4520,12 +4622,10 @@ cdfInqContents(stream_t *streamptr)
   cdf_scan_global_attr(fileID, vlistID, ngatts, &instID, &modelID, &ucla_les, uuidOfVGrid, &gridInfo);
 
   // find time dim
-  int timedimid = (unlimdimid >= 0) ? unlimdimid : cdf_time_dimid(fileID, ndims, nvars, ncdims);
-
+  int timedimid = (unlimdimid >= 0) ? unlimdimid : cdf_time_dimid(fileID, ndims, ncdims, nvars, ncvars);
   streamptr->basetime.ncdimid = timedimid;
 
-  size_t ntsteps = 0;
-  if (timedimid != CDI_UNDEFID) cdf_inq_dimlen(fileID, ncdims[timedimid].dimid, &ntsteps);
+  size_t ntsteps = (timedimid == CDI_UNDEFID) ? 0 : ncdims[timedimid].len;
   if (ntsteps > INT_MAX)
     {
       Warning("Size limit exceeded for time dimension (limit=%d)!", INT_MAX);
@@ -4535,63 +4635,34 @@ cdfInqContents(stream_t *streamptr)
   if (CDI_Debug) Message("Number of timesteps = %zu", ntsteps);
   if (CDI_Debug) Message("Time dimid = %d", streamptr->basetime.ncdimid);
 
-  // read ncdims
-  for (int ncdimid = 0; ncdimid < ndims; ncdimid++)
+  // set T_AXIS dimtype
+  for (int gdimid = 0; gdimid < ndims; gdimid++)
     {
-      cdf_inq_dimlen(fileID, ncdims[ncdimid].dimid, &ncdims[ncdimid].len);
-      cdf_inq_dimname(fileID, ncdims[ncdimid].dimid, ncdims[ncdimid].name);
-      if (timedimid == ncdimid) ncdims[ncdimid].dimtype = T_AXIS;
+      if (timedimid == gdimid) ncdims[gdimid].dimtype = T_AXIS;
     }
 
   stream_set_ncdims(streamptr, ndims, ncdims);
 
-  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "cdfScanVarAttr");
+  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "scan_vars_attr");
 
   // scan attributes of all variables
-  cdfScanVarAttr(nvars, ncvars, ndims, ncdims, timedimid, modelID, format);
+  set_vars_timetype(nvars, ncvars, timedimid);
+  scan_vars_attr(nvars, ncvars, ndims, ncdims, modelID);
+  verify_vars_attr(nvars, ncvars, ncdims);
 
-  cdfVerifyVarAttr(nvars, ncvars, ncdims);
+  if (CDI_Convert_Cubesphere) check_cube_sphere(vlistID, nvars, ncvars, ncdims);
 
-  if (CDI_Convert_Cubesphere)
-    {
-      bool isGeosData = check_cube_sphere(vlistID, nvars, ncvars, ncdims);
-      if (CDI_Debug) Message("isGeosData %d", isGeosData);
-    }
+  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars1d");
 
-  if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find coordinates vars");
-
-  // find coordinates vars
-  for (int ncdimid = 0; ncdimid < ndims; ncdimid++)
-    {
-      for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
-        {
-          ncvar_t *ncvar = &ncvars[ncvarid];
-          if (ncvar->ndims == 1)
-            {
-              if (timedimid != CDI_UNDEFID && timedimid == ncvar->dimids[0])
-                {
-                  if (ncvar->varStatus != CoordVar) cdf_set_var(ncvar, DataVar);
-                }
-              else
-                {
-                  //  if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar);
-                }
-              // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar);
-
-              if (ncdimid == ncvar->dimids[0] && ncdims[ncdimid].ncvarid == CDI_UNDEFID)
-                if (str_is_equal(ncvar->name, ncdims[ncdimid].name))
-                  {
-                    ncdims[ncdimid].ncvarid = ncvarid;
-                    ncvar->varStatus = CoordVar;
-                  }
-            }
-        }
-    }
+  find_varying_data_vars1d(timedimid, nvars, ncvars);
 
   // find time vars
+  bool timeHasUnits = false;
+  bool timeHasBounds = false;
+  bool timeClimatology = false;
   find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &timeHasUnits, &timeHasBounds, &timeClimatology);
 
-  leadtime_id = find_leadtime(nvars, ncvars, timedimid);
+  int leadtime_id = find_leadtime(nvars, ncvars, timedimid);
   if (leadtime_id != CDI_UNDEFID) ncvars[leadtime_id].varStatus = CoordVar;
 
   // check ncvars
@@ -4627,36 +4698,8 @@ cdfInqContents(stream_t *streamptr)
     }
   */
 
-  // Set coordinates varids (att: associate)
-  for (int ncvarid = 0; ncvarid < nvars; ncvarid++)
-    {
-      ncvar_t *ncvar = &ncvars[ncvarid];
-      if (ncvar->varStatus == DataVar && ncvar->ncoordvars)
-        {
-          for (int i = 0; i < ncvar->ncoordvars; i++)
-            {
-              int ncvaridc = ncvar->coordvarids[i];
-              if (ncvaridc != CDI_UNDEFID)
-                {
-                  ncvar_t *ncvarc = &ncvars[ncvaridc];
-                  // clang-format off
-                  if      (ncvarc->isLon || ncvarc->isXaxis) ncvar->xvarid = ncvaridc;
-                  else if (ncvarc->isLat || ncvarc->isYaxis) ncvar->yvarid = ncvaridc;
-                  else if (ncvarc->isZaxis)                  ncvar->zvarid = ncvaridc;
-                  else if (ncvarc->isTaxis)                  ncvar->tvarid = ncvaridc;
-                  else if (ncvarc->isCharAxis)               ncvar->cvarids[i] = ncvaridc;
-                  else if (ncvarc->printWarning)
-                    {
-                      Warning("Coordinates variable %s can't be assigned!", ncvarc->name);
-                      ncvarc->printWarning = false;
-                    }
-                  // clang-format on
-                }
-            }
-        }
-    }
+  set_coordinates_varids(nvars, ncvars);
 
-  // set dim type
   cdf_set_dimtype(nvars, ncvars, ncdims);
 
   // read ECHAM VCT if present
@@ -4737,12 +4780,9 @@ cdfInqContents(stream_t *streamptr)
           streamptr->basetime.leadtimeid = leadtime_id;
           taxis0.type = TAXIS_FORECAST;
 
-          int timeunit = -1;
-          if (ncvars[leadtime_id].units[0] != 0) timeunit = scan_time_units(ncvars[leadtime_id].units);
+          int timeunit = (ncvars[leadtime_id].units[0] != 0) ? scan_time_units(ncvars[leadtime_id].units) : -1;
           if (timeunit == -1) timeunit = taxis0.unit;
           taxis0.fc_unit = timeunit;
-
-          set_forecast_time(fcreftime, &taxis0);
         }
     }
 
diff --git a/src/stream_cdf_o.c b/src/stream_cdf_o.c
index cd07f30a2ee6fd274b897e31f13807d947e0f8b6..987fb0514748e8247f2af414fa2003f1264e9217 100644
--- a/src/stream_cdf_o.c
+++ b/src/stream_cdf_o.c
@@ -33,14 +33,14 @@ cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
   void *data = Malloc(datasize * ((memtype == MEMTYPE_DOUBLE) ? sizeof(double) : sizeof(float)));
 
   size_t numMissVals;
-  cdf_read_record(streamptr1, memtype, data, &numMissVals);
-  cdf_write_record(streamptr2, memtype, data, numMissVals);
+  cdf_read_field(streamptr1, memtype, data, &numMissVals);
+  cdf_write_field(streamptr2, memtype, data, numMissVals);
 
   Free(data);
 }
 
 void
-cdfDefRecord(stream_t *streamptr)
+cdfDefField(stream_t *streamptr)
 {
   (void) streamptr;
 }
diff --git a/src/stream_cdf_time.c b/src/stream_cdf_time.c
index 62d8a29a998dce7b3e5354307134a6c28b5040a4..dc594c44d4d14dd8080fc484636b7cdff7f8ecfb 100644
--- a/src/stream_cdf_time.c
+++ b/src/stream_cdf_time.c
@@ -203,11 +203,9 @@ cdfDefTime(stream_t *streamptr)
     }
   else
     {
-      /* define bogus value since at this time, streamDefTimestep has
-       * not been called yet
-       * but since taxis->units is not set, it clearly will not
-       * exceed the size of unitstr_, i.e. when defining the units
-       * attribute to this value, a later redefinition will not
+      /* define bogus value since at this time, streamDefTimestep has not been called yet
+       * but since taxis->units is not set, it clearly will not exceed the size of unitstr_,
+       * i.e. when defining the units attribute to this value, a later redefinition will not
        * cause a recreation of on-disk data
        */
       for (size_t i = 0; i < CDF_MAX_TIME_UNIT_STR; ++i) unitsStr_[i] = 'a';
diff --git a/src/stream_cgribex.c b/src/stream_cgribex.c
index c625dc10d9b62169b875586a2cf909c6bd0166d8..a2c73b7f0c104ce5fc2657e94d659287bcd380b2 100644
--- a/src/stream_cgribex.c
+++ b/src/stream_cgribex.c
@@ -82,16 +82,6 @@ cgribexDelete(void *cgribex)
     }
 }
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-  int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp, unsigned char **gdsp, unsigned char **bmsp,
-                    unsigned char **bdsp, long *gribrecsize);
-#ifdef __cplusplus
-}
-#endif
-
 static size_t
 cgribexSection2Length(void *gribbuffer, size_t gribbuffersize)
 {
@@ -201,10 +191,10 @@ cgribexGetTimeUnit(int *isec1)
     case ISEC1_TABLE4_DAY:       timeunit = TUNIT_DAY;       break;
     default:
       if (lprint)
-	{
-	  Warning("GRIB time unit %d unsupported!", ISEC1_TimeUnit);
-	  lprint = false;
-	}
+	    {
+	      Warning("GRIB time unit %d unsupported!", ISEC1_TimeUnit);
+	      lprint = false;
+	    }
       break;
     }
   // clang-format on
@@ -237,10 +227,10 @@ cgribexGetTsteptype(int timerange)
     case 10:  tsteptype = TSTEP_INSTANT3; break;
     default:
       if (lprint)
-	{
-	  Warning("Time range indicator %d unsupported, set to 0!", timerange);
-	  lprint = false;
-	}
+    	{
+	      Warning("Time range indicator %d unsupported, set to 0!", timerange);
+	      lprint = false;
+	    }
       break;
     }
   // clang-format on
@@ -758,6 +748,8 @@ cgribexSkipRecords(int fileID)
       size_t recsize = gribGetSize(fileID);
       if (recsize == 0) Error("Skipping of %d records failed!", CDI_Skip_Records);
 
+      grib_check_recsize(0, recsize);
+
       off_t recpos = fileGetPos(fileID);
       fileSetPos(fileID, recpos, SEEK_CUR);
     }
@@ -818,6 +810,7 @@ cgribexScanTimestep1(stream_t *streamptr)
           break;
         }
 
+      grib_check_recsize(1, recsize);
       ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
       size_t readsize = recsize;
@@ -984,6 +977,7 @@ cgribexScanTimestep2(stream_t *streamptr)
           break;
         }
 
+      grib_check_recsize(1, recsize);
       ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
       size_t readsize = recsize;
@@ -1172,6 +1166,7 @@ cgribexScanTimestep(stream_t *streamptr)
               break;
             }
 
+          grib_check_recsize(1, recsize);
           ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
           size_t readsize = recsize;
diff --git a/src/stream_ext.c b/src/stream_ext.c
index 8f4e7ee86e3972ec99471cea938bae0e2e25c938..616ef92dc08043afedb8b2f06dc9aec377039ef0 100644
--- a/src/stream_ext.c
+++ b/src/stream_ext.c
@@ -38,43 +38,6 @@ extDefDatatype(int datatype, int *prec, int *number)
   *prec = (datatype == CDI_DATATYPE_FLT64 || datatype == CDI_DATATYPE_CPX64) ? EXSE_PREC_FP64 : EXSE_PREC_FP32;
 }
 
-/* not used
-int extInqRecord(stream_t *streamptr, int *varID, int *levelID)
-{
-  int status;
-  int fileID;
-  int icode, ilevel;
-  int zaxisID = -1;
-  int header[4];
-  int vlistID;
-  void *extp = streamptr->record->objectp;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  *varID   = -1;
-  *levelID = -1;
-
-  status = extRead(fileID, extp);
-  if ( status != 0 ) return 0;
-
-  extInqHeader(extp, header);
-
-  icode  = header[1];
-  ilevel = header[2];
-
-  *varID = vlistInqVarID(vlistID, icode);
-
-  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
-
-  zaxisID = vlistInqVarZaxis(vlistID, *varID);
-
-  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
-
-  return 1;
-}
-*/
-
 static void
 ext_read_recordSP(stream_t *streamptr, float *data, size_t *numMissVals)
 {
@@ -140,7 +103,7 @@ ext_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals)
 }
 
 void
-ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
+ext_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
 {
   if (memtype == MEMTYPE_DOUBLE)
     ext_read_recordDP(streamptr, (double *) data, numMissVals);
@@ -149,13 +112,13 @@ ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVal
 }
 
 void
-extCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+extCopyField(stream_t *streamptr2, stream_t *streamptr1)
 {
   streamFCopyRecord(streamptr2, streamptr1, "EXTRA");
 }
 
 void
-extDefRecord(stream_t *streamptr)
+extDefField(stream_t *streamptr)
 {
   Record *record = streamptr->record;
 
@@ -192,7 +155,7 @@ ext_write_recordDP(stream_t *streamptr, const double *data)
 }
 
 void
-ext_write_record(stream_t *streamptr, int memtype, const void *data)
+ext_write_field(stream_t *streamptr, int memtype, const void *data)
 {
   if (memtype == MEMTYPE_DOUBLE)
     ext_write_recordDP(streamptr, (const double *) data);
diff --git a/src/stream_ext.h b/src/stream_ext.h
index 3f6d3516066c1b0bf4c1c9bf9b5ed09fafd7d17d..1a0b331a56eb83d7de9c9af8755398a83eb48c76 100644
--- a/src/stream_ext.h
+++ b/src/stream_ext.h
@@ -8,11 +8,10 @@
 int extInqContents(stream_t *streamptr);
 int extInqTimestep(stream_t *streamptr, int tsID);
 
-int extInqRecord(stream_t *streamptr, int *varID, int *levelID);
-void extDefRecord(stream_t *streamptr);
-void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
-void ext_write_record(stream_t *streamptr, int memtype, const void *data);
+void extDefField(stream_t *streamptr);
+void extCopyField(stream_t *streamptr2, stream_t *streamptr1);
+void ext_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
+void ext_write_field(stream_t *streamptr, int memtype, const void *data);
 
 void extReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals);
 void extWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/src/stream_grb.c b/src/stream_grb.c
index a6985f86ba2c0273b7d81a4329f1ed21728fcea5..9441a53e3876091937dc1881c924dd5b05afde71 100644
--- a/src/stream_grb.c
+++ b/src/stream_grb.c
@@ -250,19 +250,8 @@ grbBitsPerValue(int datatype)
   return bitsPerValue;
 }
 
-/*
-int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
-{
-  int status;
-
-  status = cgribexInqRecord(streamptr, varID, levelID);
-
-  return (status);
-}
-*/
-
 void
-grbDefRecord(stream_t *streamptr)
+grbDefField(stream_t *streamptr)
 {
   UNUSED(streamptr);
 }
diff --git a/src/stream_grb.h b/src/stream_grb.h
index e187d4f963e17b84f37b92782ecc156502491f96..123a9a77f74c64f57f031b923058d0707387d8de 100644
--- a/src/stream_grb.h
+++ b/src/stream_grb.h
@@ -8,6 +8,12 @@ bool zaxis_units_is_Pa(int zaxisID);
 void ensureBufferSize(size_t requiredSize, size_t *curSize, void **buffer);
 int grbDecompress(size_t recsize, size_t *buffersize, void **gribbuffer);
 
+static inline void
+grib_check_recsize(int version, size_t recsize)
+{
+  if (recsize > 0xFFFFFFFF) Error("GRIB%d record size=%zu limit exceeded (max=%zu)", version, recsize, 0xFFFFFFFF);
+}
+
 static inline bool
 gribbyte_get_bit(int number, int bit)
 {
@@ -31,11 +37,10 @@ long grbInqContents(stream_t *streamptr);
 int fdbInqTimestep(stream_t *streamptr, int tsID);
 int grbInqTimestep(stream_t *streamptr, int tsID);
 
-int grbInqRecord(stream_t *streamptr, int *varID, int *levelID);
-void grbDefRecord(stream_t *streamptr);
-void grb_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
-void grb_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals);
-void grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
+void grbDefField(stream_t *streamptr);
+void grb_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
+void grb_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals);
+void grbCopyField(stream_t *streamptr2, stream_t *streamptr1);
 
 void grb_read_var(stream_t *streamptr, int varID, int memtype, void *data, size_t *numMissVals);
 void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, size_t numMissVals);
diff --git a/src/stream_gribapi.c b/src/stream_gribapi.c
index 399988356fca6e65a395d3383290169c4d8bbe5d..30c14eba1bfd748fa5a7910663f93bc2ba17ec2d 100644
--- a/src/stream_gribapi.c
+++ b/src/stream_gribapi.c
@@ -1258,6 +1258,7 @@ gribapiScanTimestep1(stream_t *streamptr)
           break;
         }
 
+      grib_check_recsize(2, recsize);
       ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
       size_t readsize = recsize;
@@ -1419,6 +1420,7 @@ gribapiScanTimestep2(stream_t *streamptr)
           break;
         }
 
+      grib_check_recsize(2, recsize);
       ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
       size_t readsize = recsize;
@@ -1594,6 +1596,7 @@ gribapiScanTimestep(stream_t *streamptr)
               break;
             }
 
+          grib_check_recsize(2, recsize);
           ensureBufferSize(recsize, &buffersize, &gribbuffer);
 
           size_t readsize = recsize;
diff --git a/src/stream_ieg.c b/src/stream_ieg.c
index a913e69e787aad1d403bf731172ca797fde70652..4194ed0373cba5a384ee4cbfc4515d54dbee1aa6 100644
--- a/src/stream_ieg.c
+++ b/src/stream_ieg.c
@@ -90,7 +90,7 @@ ieg_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals)
 }
 
 void
-ieg_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
+ieg_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
 {
   if (memtype == MEMTYPE_DOUBLE)
     ieg_read_recordDP(streamptr, (double *) data, numMissVals);
@@ -418,13 +418,13 @@ iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
 }
 
 void
-iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+iegCopyField(stream_t *streamptr2, stream_t *streamptr1)
 {
   streamFCopyRecord(streamptr2, streamptr1, "IEG");
 }
 
 void
-iegDefRecord(stream_t *streamptr)
+iegDefField(stream_t *streamptr)
 {
   Record *record = streamptr->record;
 
@@ -507,7 +507,7 @@ ieg_write_recordDP(stream_t *streamptr, const double *data)
 }
 
 void
-ieg_write_record(stream_t *streamptr, int memtype, const void *data)
+ieg_write_field(stream_t *streamptr, int memtype, const void *data)
 {
   if (memtype == MEMTYPE_DOUBLE)
     ieg_write_recordDP(streamptr, (const double *) data);
diff --git a/src/stream_ieg.h b/src/stream_ieg.h
index a099cdaf4b96dbb58248c015a23926a2685d5d80..85e841411cb4066f04e1bc7ee740457dda2bd181 100644
--- a/src/stream_ieg.h
+++ b/src/stream_ieg.h
@@ -8,11 +8,10 @@
 int iegInqContents(stream_t *streamptr);
 int iegInqTimestep(stream_t *streamptr, int tsID);
 
-int iegInqRecord(stream_t *streamptr, int *varID, int *levelID);
-void iegDefRecord(stream_t *streamptr);
-void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void ieg_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
-void ieg_write_record(stream_t *streamptr, int memtype, const void *data);
+void iegDefField(stream_t *streamptr);
+void iegCopyField(stream_t *streamptr2, stream_t *streamptr1);
+void ieg_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
+void ieg_write_field(stream_t *streamptr, int memtype, const void *data);
 
 void iegReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals);
 void iegWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/src/stream_read.c b/src/stream_read.c
index 059547401207df92a4b16d4d59d9eecc7b5e81ef..c5655dd332ba5042628bcfb04c5e416865c50a82 100644
--- a/src/stream_read.c
+++ b/src/stream_read.c
@@ -237,19 +237,19 @@ stream_read_record(int streamID, int memtype, void *data, size_t *numMissVals)
   switch (cdiBaseFiletype(streamptr->filetype))
     {
 #ifdef HAVE_LIBGRIB
-    case CDI_FILETYPE_GRIB: grb_read_record(streamptr, memtype, data, numMissVals); break;
+    case CDI_FILETYPE_GRIB: grb_read_field(streamptr, memtype, data, numMissVals); break;
 #endif
 #ifdef HAVE_LIBSERVICE
-    case CDI_FILETYPE_SRV: srv_read_record(streamptr, memtype, data, numMissVals); break;
+    case CDI_FILETYPE_SRV: srv_read_field(streamptr, memtype, data, numMissVals); break;
 #endif
 #ifdef HAVE_LIBEXTRA
-    case CDI_FILETYPE_EXT: ext_read_record(streamptr, memtype, data, numMissVals); break;
+    case CDI_FILETYPE_EXT: ext_read_field(streamptr, memtype, data, numMissVals); break;
 #endif
 #ifdef HAVE_LIBIEG
-    case CDI_FILETYPE_IEG: ieg_read_record(streamptr, memtype, data, numMissVals); break;
+    case CDI_FILETYPE_IEG: ieg_read_field(streamptr, memtype, data, numMissVals); break;
 #endif
 #ifdef HAVE_LIBNETCDF
-    case CDI_FILETYPE_NETCDF: cdf_read_record(streamptr, memtype, data, numMissVals); break;
+    case CDI_FILETYPE_NETCDF: cdf_read_field(streamptr, memtype, data, numMissVals); break;
 #endif
     default: Error("%s support not compiled in!", strfiletype(streamptr->filetype));
     }
@@ -258,7 +258,7 @@ stream_read_record(int streamID, int memtype, void *data, size_t *numMissVals)
 }
 
 void
-streamReadRecord(int streamID, double *data, SizeType *numMissVals)
+streamReadField(int streamID, double *data, SizeType *numMissVals)
 {
   size_t numMiss = 0;
   stream_read_record(streamID, MEMTYPE_DOUBLE, (void *) data, &numMiss);
@@ -266,7 +266,7 @@ streamReadRecord(int streamID, double *data, SizeType *numMissVals)
 }
 
 void
-streamReadRecordF(int streamID, float *data, SizeType *numMissVals)
+streamReadFieldF(int streamID, float *data, SizeType *numMissVals)
 {
   size_t numMiss = 0;
   stream_read_record(streamID, MEMTYPE_FLOAT, (void *) data, &numMiss);
diff --git a/src/stream_record.c b/src/stream_record.c
index a8c6b3ec9818da91aba3d70563e335345c8d2aa1..114b0df4065a60eb624c4f4eff57a749c80807cf 100644
--- a/src/stream_record.c
+++ b/src/stream_record.c
@@ -97,7 +97,7 @@ cdiInitRecord(stream_t *streamptr)
 }
 
 void
-streamInqRecord(int streamID, int *varID, int *levelID)
+streamInqField(int streamID, int *varID, int *levelID)
 {
   check_parg(varID);
   check_parg(levelID);
@@ -146,7 +146,7 @@ The function streamDefRecord defines the meta-data of the next record.
 @EndFunction
 */
 void
-streamDefRecord(int streamID, int varID, int levelID)
+streamDefField(int streamID, int varID, int levelID)
 {
   stream_t *streamptr = stream_to_pointer(streamID);
 
@@ -178,21 +178,21 @@ streamDefRecord(int streamID, int varID, int levelID)
   switch (cdiBaseFiletype(streamptr->filetype))
     {
 #ifdef HAVE_LIBGRIB
-    case CDI_FILETYPE_GRIB: grbDefRecord(streamptr); break;
+    case CDI_FILETYPE_GRIB: grbDefField(streamptr); break;
 #endif
 #ifdef HAVE_LIBSERVICE
-    case CDI_FILETYPE_SRV: srvDefRecord(streamptr); break;
+    case CDI_FILETYPE_SRV: srvDefField(streamptr); break;
 #endif
 #ifdef HAVE_LIBEXTRA
-    case CDI_FILETYPE_EXT: extDefRecord(streamptr); break;
+    case CDI_FILETYPE_EXT: extDefField(streamptr); break;
 #endif
 #ifdef HAVE_LIBIEG
-    case CDI_FILETYPE_IEG: iegDefRecord(streamptr); break;
+    case CDI_FILETYPE_IEG: iegDefField(streamptr); break;
 #endif
 #ifdef HAVE_LIBNETCDF
     case CDI_FILETYPE_NETCDF:
       if (streamptr->accessmode == 0) cdfEndDef(streamptr);
-      cdfDefRecord(streamptr);
+      cdfDefField(streamptr);
       break;
 #endif
     default: Error("%s support not compiled in!", strfiletype(streamptr->filetype)); break;
@@ -200,7 +200,7 @@ streamDefRecord(int streamID, int varID, int levelID)
 }
 
 void
-streamCopyRecord(int streamID2, int streamID1)
+streamCopyField(int streamID2, int streamID1)
 {
   stream_t *streamptr1 = stream_to_pointer(streamID1), *streamptr2 = stream_to_pointer(streamID2);
   int filetype1 = streamptr1->filetype, filetype2 = streamptr2->filetype, filetype = CDI_FILETYPE_UNDEF;
@@ -213,16 +213,16 @@ streamCopyRecord(int streamID2, int streamID1)
   switch (cdiBaseFiletype(filetype))
     {
 #ifdef HAVE_LIBGRIB
-    case CDI_FILETYPE_GRIB: grbCopyRecord(streamptr2, streamptr1); break;
+    case CDI_FILETYPE_GRIB: grbCopyField(streamptr2, streamptr1); break;
 #endif
 #ifdef HAVE_LIBSERVICE
-    case CDI_FILETYPE_SRV: srvCopyRecord(streamptr2, streamptr1); break;
+    case CDI_FILETYPE_SRV: srvCopyField(streamptr2, streamptr1); break;
 #endif
 #ifdef HAVE_LIBEXTRA
-    case CDI_FILETYPE_EXT: extCopyRecord(streamptr2, streamptr1); break;
+    case CDI_FILETYPE_EXT: extCopyField(streamptr2, streamptr1); break;
 #endif
 #ifdef HAVE_LIBIEG
-    case CDI_FILETYPE_IEG: iegCopyRecord(streamptr2, streamptr1); break;
+    case CDI_FILETYPE_IEG: iegCopyField(streamptr2, streamptr1); break;
 #endif
 #ifdef HAVE_LIBNETCDF
     case CDI_FILETYPE_NETCDF: cdfCopyRecord(streamptr2, streamptr1); break;
diff --git a/src/stream_srv.c b/src/stream_srv.c
index b38d669198c4ac8966cf1d004fee6415080a5ee9..fa1beba762d18c1133569a7ef733b72232458318 100644
--- a/src/stream_srv.c
+++ b/src/stream_srv.c
@@ -34,43 +34,6 @@ srvDefDatatype(int datatype)
   return (datatype == CDI_DATATYPE_FLT64) ? EXSE_PREC_FP64 : EXSE_PREC_FP32;
 }
 
-/* not used
-int srvInqRecord(stream_t *streamptr, int *varID, int *levelID)
-{
-  int status;
-  int fileID;
-  int icode, ilevel;
-  int zaxisID = -1;
-  int header[8];
-  int vlistID;
-  void *srvp = streamptr->record->objectp;
-
-  vlistID = streamptr->vlistID;
-  fileID  = streamptr->fileID;
-
-  *varID   = -1;
-  *levelID = -1;
-
-  status = srvRead(fileID, srvp);
-  if ( status != 0 ) return (0);
-
-  srvInqHeader(srvp, header);
-
-  icode  = header[0];
-  ilevel = header[1];
-
-  *varID = vlistInqVarID(vlistID, icode);
-
-  if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode);
-
-  zaxisID = vlistInqVarZaxis(vlistID, *varID);
-
-  *levelID = zaxisInqLevelID(zaxisID, (double) ilevel);
-
-  return 1;
-}
-*/
-
 static void
 srv_read_recordSP(stream_t *streamptr, float *data, size_t *numMissVals)
 {
@@ -130,7 +93,7 @@ srv_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals)
 }
 
 void
-srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
+srv_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals)
 {
   if (memtype == MEMTYPE_DOUBLE)
     srv_read_recordDP(streamptr, (double *) data, numMissVals);
@@ -139,13 +102,13 @@ srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVal
 }
 
 void
-srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1)
+srvCopyField(stream_t *streamptr2, stream_t *streamptr1)
 {
   streamFCopyRecord(streamptr2, streamptr1, "SRV");
 }
 
 void
-srvDefRecord(stream_t *streamptr)
+srvDefField(stream_t *streamptr)
 {
   Record *record = streamptr->record;
 
@@ -198,7 +161,7 @@ srv_write_recordDP(stream_t *streamptr, const double *data)
 }
 
 void
-srv_write_record(stream_t *streamptr, int memtype, const void *data)
+srv_write_field(stream_t *streamptr, int memtype, const void *data)
 {
   if (memtype == MEMTYPE_DOUBLE)
     srv_write_recordDP(streamptr, (const double *) data);
diff --git a/src/stream_srv.h b/src/stream_srv.h
index adeaf679200828310ac9245e697cac6e25f75b7b..8e13653b13061c77b13ec394c32440467b01a678 100644
--- a/src/stream_srv.h
+++ b/src/stream_srv.h
@@ -8,11 +8,10 @@
 int srvInqContents(stream_t *streamptr);
 int srvInqTimestep(stream_t *streamptr, int tsID);
 
-int srvInqRecord(stream_t *streamptr, int *varID, int *levelID);
-void srvDefRecord(stream_t *streamptr);
-void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1);
-void srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
-void srv_write_record(stream_t *streamptr, int memtype, const void *data);
+void srvDefField(stream_t *streamptr);
+void srvCopyField(stream_t *streamptr2, stream_t *streamptr1);
+void srv_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals);
+void srv_write_field(stream_t *streamptr, int memtype, const void *data);
 
 void srvReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals);
 void srvWriteVarDP(stream_t *streamptr, int varID, const double *data);
diff --git a/src/stream_write.c b/src/stream_write.c
index 4383cb782b7d3883762bc4ecf426782d071cc3fa..11f781e5abdcdea85783d3637d36152b55af8816 100644
--- a/src/stream_write.c
+++ b/src/stream_write.c
@@ -286,19 +286,19 @@ stream_write_record(int streamID, int memtype, const void *data, SizeType numMis
   switch (cdiBaseFiletype(streamptr->filetype))
     {
 #ifdef HAVE_LIBGRIB
-    case CDI_FILETYPE_GRIB: grb_write_record(streamptr, memtype, data, (size_t) numMissVals); break;
+    case CDI_FILETYPE_GRIB: grb_write_field(streamptr, memtype, data, (size_t) numMissVals); break;
 #endif
 #ifdef HAVE_LIBSERVICE
-    case CDI_FILETYPE_SRV: srv_write_record(streamptr, memtype, data); break;
+    case CDI_FILETYPE_SRV: srv_write_field(streamptr, memtype, data); break;
 #endif
 #ifdef HAVE_LIBEXTRA
-    case CDI_FILETYPE_EXT: ext_write_record(streamptr, memtype, data); break;
+    case CDI_FILETYPE_EXT: ext_write_field(streamptr, memtype, data); break;
 #endif
 #ifdef HAVE_LIBIEG
-    case CDI_FILETYPE_IEG: ieg_write_record(streamptr, memtype, data); break;
+    case CDI_FILETYPE_IEG: ieg_write_field(streamptr, memtype, data); break;
 #endif
 #ifdef HAVE_LIBNETCDF
-    case CDI_FILETYPE_NETCDF: cdf_write_record(streamptr, memtype, data, (size_t) numMissVals); break;
+    case CDI_FILETYPE_NETCDF: cdf_write_field(streamptr, memtype, data, (size_t) numMissVals); break;
 #endif
     default: Error("%s support not compiled in!", strfiletype(streamptr->filetype));
     }
@@ -322,13 +322,13 @@ The values are converted to the external data type of the variable, if necessary
 @EndFunction
 */
 void
-streamWriteRecord(int streamID, const double *data, SizeType numMissVals)
+streamWriteField(int streamID, const double *data, SizeType numMissVals)
 {
   stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, numMissVals);
 }
 
 void
-streamWriteRecordF(int streamID, const float *data, SizeType numMissVals)
+streamWriteFieldF(int streamID, const float *data, SizeType numMissVals)
 {
   stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, numMissVals);
 }
diff --git a/src/taxis.c b/src/taxis.c
index a22ffb4e27cb83a6ebc188fd7f2d9ce5bccc1737..5acf45b5715e6dba9f64f41f1473927f3a56ddfd 100644
--- a/src/taxis.c
+++ b/src/taxis.c
@@ -1289,6 +1289,7 @@ cdi_decode_timeval(double timevalue, const taxis_t *taxis)
   return (taxis->type == TAXIS_ABSOLUTE) ? split_timevalue(timevalue, taxis->unit) : rtimeval2datetime(timevalue, taxis);
 }
 
+/*
 static int64_t
 datetime2seconds(CdiDateTime datetime)
 {
@@ -1305,7 +1306,7 @@ datetime2seconds(CdiDateTime datetime)
 
   return seconds;
 }
-
+*/
 double
 cdi_encode_timeval(CdiDateTime datetime, taxis_t *taxis)
 {
@@ -1322,10 +1323,12 @@ cdi_encode_timeval(CdiDateTime datetime, taxis_t *taxis)
           int64_t xdate = cdiDate_get(datetime.date);
           timeValue = (double) xdate / 100 + copysign((double) (datetime.date.day != 0) * 0.5, (double) xdate);
         }
+      /*
       else if (taxis->unit == TUNIT_SECOND)
         {
           timeValue = (double) datetime2seconds(datetime);
         }
+      */
       else
         {
           int hour, minute, second, ms;
diff --git a/src/vlist.c b/src/vlist.c
index 9a4c817ce0cdbf94acc5f92d8dfbfc98a8fcc848..be99645856a386166af6443eb295fb48b9dd6be2 100644
--- a/src/vlist.c
+++ b/src/vlist.c
@@ -948,7 +948,7 @@ vlistNvars(int vlistID)
 }
 
 int
-vlistNumRecords(int vlistID)
+vlistNumFields(int vlistID)
 {
   vlist_t *vlistptr = vlist_to_pointer(vlistID);