LCOV - code coverage report
Current view: top level - shared/common/src/21_hashfuncs - m_hash_md5.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 45.7 % 46 21
Test Date: 2026-09-21 22:40:37 Functions: 33.3 % 9 3

            Line data    Source code
       1              : !!****m* ABINIT/m_hash_md5
       2              : !! NAME
       3              : !!  m_hash_md5
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides resources to calculate MD5 checksums.
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2016-2026 ABINIT group (Yann Pouillon)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_hash_md5
      23              : 
      24              :   use, intrinsic :: iso_c_binding
      25              :   use m_abicore
      26              : 
      27              :   implicit none
      28              : 
      29              :   private
      30              : 
      31              :   public :: md5_check             ! Checks whether two MD5 sums are identical
      32              :   public :: md5_sum_from_file     ! Computes a MD5 sum from a file
      33              :   public :: md5_sum_from_string   ! Computes a MD5 sum from a text string
      34              : 
      35              :   type :: md5_context_t
      36              :     private
      37              :     type(c_ptr) :: ptr = C_NULL_PTR
      38              :   end type md5_context_t
      39              : 
      40              :   interface
      41              :     function MD5_Context_New() bind(c, name="MD5_Context_New")
      42              :       import
      43              :       type(c_ptr) :: MD5_Context_New
      44              :     end function MD5_Context_New
      45              :   end interface
      46              :   interface
      47              :     subroutine MD5_Digest_File(fname, retval) bind(c, name="MD5_Digest_File")
      48              :       import
      49              :       character(kind=c_char) :: fname(*)
      50              :       character(kind=c_char) :: retval(33)
      51              :     end subroutine MD5_Digest_File
      52              :   end interface
      53              :   interface
      54              :     subroutine MD5_Final(retval, ctx) bind(c, name="MD5_Final")
      55              :       import
      56              :       character(kind=c_char) :: retval(33)
      57              :       type(c_ptr), value :: ctx
      58              :     end subroutine MD5_Final
      59              :   end interface
      60              :   interface
      61              :     subroutine MD5_Init(ctx) bind(c, name="MD5_Init")
      62              :       import
      63              :       type(c_ptr), value :: ctx
      64              :     end subroutine MD5_Init
      65              :   end interface
      66              :   interface
      67              :     subroutine MD5_Update(ctx, buffer, bufsize) bind(c, name="MD5_Update")
      68              :       import
      69              :       type(c_ptr), value :: ctx
      70              :       character(kind=c_char) :: buffer(*)
      71              :       integer(c_int), value :: bufsize
      72              :     end subroutine MD5_Update
      73              :   end interface
      74              : 
      75              : contains  !===========================================================
      76              : !!***
      77              : 
      78              : !!****f* m_hash_md5/md5_check
      79              : !! NAME
      80              : !! md5_check
      81              : !!
      82              : !! FUNCTION
      83              : !!  Checks whether two MD5 sums are identical.
      84              : !!
      85              : !! INPUTS
      86              : !!  sum1 = the first sum to compare
      87              : !!  sum2 = the second sum to compare
      88              : !!
      89              : !! OUTPUT
      90              : !!  boolean telling whether the two sums are identical
      91              : !!
      92              : !! NOTES
      93              : !!  Created a function to be able to add more operations than just checking
      94              : !!  the equality of the sums.
      95              : !!
      96              : !! SOURCE
      97              : 
      98            0 : function md5_check(sum1,sum2)
      99              : 
     100              : !Arguments ------------------------------------
     101              :   character(len=32),intent(in) :: sum1
     102              :   character(len=32),intent(in) :: sum2
     103              : 
     104              : !Local variables-------------------------------
     105              :   logical :: md5_check
     106              : 
     107              : ! *********************************************************************
     108              : 
     109            0 :   md5_check = ( sum1 == sum2 )
     110              : 
     111            0 : end function md5_check
     112              : !!***
     113              : 
     114              : ! ---------------------------------------------------------------------
     115              : 
     116              : !!****f* m_hash_md5/md5_sum_from_file
     117              : !! NAME
     118              : !! md5_sum_from_file
     119              : !!
     120              : !! FUNCTION
     121              : !!  Computes a MD5 sum from a file.
     122              : !!
     123              : !! INPUTS
     124              : !!  fname = path to the file
     125              : !!
     126              : !! OUTPUT
     127              : !!  String representing the MD5 sum of the file
     128              : !!
     129              : !! SOURCE
     130              : 
     131         1572 : function md5_sum_from_file(fname)
     132              : 
     133              : !Arguments ------------------------------------
     134              :   character(len=*),intent(in) :: fname
     135              : 
     136              : !Local variables-------------------------------
     137              :   character(len=32) :: md5_sum_from_file
     138              :   character(kind=c_char) :: retval(33)
     139         1572 :   character(kind=c_char), allocatable :: path(:)
     140              :   integer :: strlen
     141              : 
     142              : ! *********************************************************************
     143              : 
     144              :   ! Translate file name to C
     145         1572 :   strlen = len_trim(fname)
     146         4716 :   ABI_MALLOC(path,(strlen+1))
     147         1572 :   call f_to_c_string(fname, path)
     148              : 
     149              :   ! Get MD5 sum from C
     150         1572 :   call MD5_Digest_file(path, retval)
     151         1572 :   call c_to_f_string(retval, md5_sum_from_file)
     152              : 
     153              :   ! Clean up the mess
     154         1572 :   ABI_FREE(path)
     155              : 
     156         1572 : end function md5_sum_from_file
     157              : !!***
     158              : 
     159              : ! ---------------------------------------------------------------------
     160              : 
     161              : !!****f* m_hash_md5/md5_sum_from_string
     162              : !! NAME
     163              : !! md5_sum_from_string
     164              : !!
     165              : !! FUNCTION
     166              : !!  Computes a MD5 sum from a string.
     167              : !!
     168              : !! INPUTS
     169              : !!  text = string to process
     170              : !!
     171              : !! OUTPUT
     172              : !!  String representing the MD5 sum of the argument
     173              : !!
     174              : !! SOURCE
     175              : 
     176            0 : function md5_sum_from_string(text)
     177              : 
     178              : !Arguments ------------------------------------
     179              :   character(len=*), intent(in) :: text
     180              : 
     181              : !Local variables-------------------------------
     182              :   character(len=32) :: md5_sum_from_string
     183              :   type(md5_context_t) :: ctx
     184              : 
     185              : ! *********************************************************************
     186              : 
     187            0 :   call hash_init(ctx)
     188            0 :   call hash_update(ctx, text, len_trim(text))
     189            0 :   call hash_final(md5_sum_from_string, ctx)
     190              : 
     191            0 : end function md5_sum_from_string
     192              : !!***
     193              : 
     194              : ! ========================= Private functions =========================
     195              : 
     196              : !!****f* m_hash_md5/hash_final
     197              : !! NAME
     198              : !!  hash_final
     199              : !!
     200              : !! FUNCTION
     201              : !!  Builds the final return value of the MD5 checksum.
     202              : !!
     203              : !! INPUTS
     204              : !!  ctx = MD5 context object
     205              : !!
     206              : !! OUTPUT
     207              : !!  retval = string containing the MD5 checksum
     208              : !!
     209              : !! SOURCE
     210              : 
     211            0 : subroutine hash_final(retval, ctx)
     212              : 
     213              : !Arguments ------------------------------------
     214              :   character(len=32), intent(out) :: retval
     215              :   type(md5_context_t), intent(inout) :: ctx
     216              : 
     217              : !Local variables-------------------------------
     218              :   character(kind=c_char) :: c_retval(33)
     219              : 
     220              : ! *********************************************************************
     221              : 
     222            0 :   call MD5_Final(c_retval, ctx%ptr)
     223            0 :   call c_to_f_string(c_retval, retval)
     224              : 
     225            0 : end subroutine hash_final
     226              : !!***
     227              : 
     228              : ! ---------------------------------------------------------------------
     229              : 
     230              : !!****f* m_hash_md5/hash_init
     231              : !! NAME
     232              : !! hash_init
     233              : !!
     234              : !! FUNCTION
     235              : !!  Checks whether two MD5 sums are identical.
     236              : !!
     237              : !! INPUTS
     238              : !!  ctx = MD5 context object
     239              : !!
     240              : !! SIDE EFFECTS
     241              : !!  ctx is reset to its intial values
     242              : !!
     243              : !! NOTES
     244              : !!  Created a function to be able to add more operations than just checking
     245              : !!  the equality of the sums.
     246              : !!
     247              : !! SOURCE
     248              : 
     249            0 : subroutine hash_init(ctx)
     250              : 
     251              : !Arguments ------------------------------------
     252              :   type(md5_context_t), intent(inout) :: ctx
     253              : 
     254              : ! *********************************************************************
     255              : 
     256            0 :   ctx%ptr = MD5_Context_New()
     257            0 :   call MD5_Init(ctx%ptr)
     258              : 
     259            0 : end subroutine hash_init
     260              : !!***
     261              : 
     262              : ! ---------------------------------------------------------------------
     263              : 
     264              : !!****f* m_hash_md5/hash_update
     265              : !! NAME
     266              : !! hash_update
     267              : !!
     268              : !! FUNCTION
     269              : !!  Updates a MD5 context object.
     270              : !!
     271              : !! INPUTS
     272              : !!  ctx = MD5 context object
     273              : !!  buffer = data to process
     274              : !!  bufsize = number of bytes to process
     275              : !!
     276              : !! SIDE EFFECTS
     277              : !!  ctx gets updated with the new data
     278              : !!
     279              : !! SOURCE
     280              : 
     281            0 : subroutine hash_update(ctx, buffer, bufsize)
     282              : 
     283              : !Arguments ------------------------------------
     284              :   type(md5_context_t), intent(inout) :: ctx
     285              :   character(len=*), intent(in) :: buffer
     286              :   integer, intent(in) :: bufsize
     287              : 
     288              : !Local variables-------------------------------
     289            0 :   character(kind=c_char), allocatable :: c_buffer(:)
     290              :   integer :: strlen
     291              : 
     292              : ! *********************************************************************
     293              : 
     294              :   ! Translate buffer into C
     295            0 :   strlen = len_trim(buffer)
     296              : ! allocate(c_buffer(strlen+1))
     297            0 :   ABI_MALLOC(c_buffer,(strlen+1))
     298            0 :   call f_to_c_string(trim(buffer), c_buffer)
     299              : 
     300              :   ! Update C MD5 context
     301            0 :   call MD5_Update(ctx%ptr, c_buffer, bufsize)
     302              : 
     303              :   ! Clean up the mess
     304              : ! deallocate(c_buffer)
     305            0 :   ABI_FREE(c_buffer)
     306              : 
     307            0 : end subroutine hash_update
     308              : !!***
     309              : 
     310              :                     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     311              : 
     312              :   ! Helper functions to convert between C and Fortran strings
     313              :   ! Based on the routines by Joseph M. Krahn
     314              : 
     315         1572 :   subroutine c_to_f_string(c_string, f_string)
     316              : 
     317              :     character(kind=c_char,len=1), intent(in)  :: c_string(*)
     318              :     character(len=*), intent(out) :: f_string
     319              : 
     320              :     integer :: i
     321              : 
     322         1572 :     i = 1
     323        51876 :     do while(c_string(i) /= C_NULL_CHAR .and. i <= len(f_string))
     324        50304 :         f_string(i:i) = c_string(i)
     325        50304 :         i = i + 1
     326              :     end do
     327         1572 :     if (i < len(f_string)) f_string(i:) = ' '
     328              : 
     329         1572 :   end subroutine c_to_f_string
     330              : 
     331              :   subroutine c_to_f_string_ptr(c_string, f_string)
     332              : 
     333              :     type(c_ptr),      intent(in)  :: c_string
     334              :     character(len=*), intent(out) :: f_string
     335              : 
     336              :     character(len=1, kind=c_char), pointer :: p_chars(:)
     337              :     integer :: i
     338              : 
     339              :     if (.not. c_associated(c_string)) then
     340              :         f_string = ' '
     341              :     else
     342              :         call c_f_pointer(c_string, p_chars, [huge(0)])
     343              :         i = 1
     344              :         do while(p_chars(i) /= C_NULL_CHAR .and. i <= len(f_string))
     345              :           f_string(i:i) = p_chars(i)
     346              :           i = i + 1
     347              :         end do
     348              :         if (i < len(f_string)) f_string(i:) = ' '
     349              :     end if
     350              : 
     351              :   end subroutine c_to_f_string_ptr
     352              : 
     353         1572 :   subroutine f_to_c_string(f_string, c_string)
     354              : 
     355              :     character(len=*), intent(in) :: f_string
     356              :     character(kind=c_char,len=1), intent(out) :: c_string(len_trim(f_string)+1)
     357              : 
     358              :     integer :: i, strlen
     359              : 
     360         1572 :     strlen = len_trim(f_string)
     361              : 
     362       195791 :     forall (i=1:strlen)
     363              :         c_string(i) = f_string(i:i)
     364              :     end forall
     365         1572 :     c_string(strlen+1) = C_NULL_CHAR
     366              : 
     367         1572 :   end subroutine f_to_c_string
     368              : 
     369            0 : end module m_hash_md5
     370              : !!***
        

Generated by: LCOV version 2.3-1