LCOV - code coverage report
Current view: top level - libs/testitall/src - check_file_identity.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 15.3 % 85 13
Test Date: 2026-01-12 05:34:38 Functions: 66.7 % 3 2

            Line data    Source code
       1              : #include "testitall.h"
       2              : 
       3              : /*
       4              :  * Modification bits
       5              :  *
       6              :  */
       7              : typedef enum
       8              : {
       9              :         IDENTICAL                 = 0x00, // 00000
      10              :         NOT_EQUAL                 = 0x01, // 00001
      11              :         SIZE_CHANGED              = 0x02, // 00010
      12              :         STATUS_CHANGED_TIME       = 0x04, // 00100
      13              :         MODIFICATION_TIME_CHANGED = 0x08, // 01000
      14              :         COMPARE_FAILED            = 0x10  // 10000
      15              : 
      16              : } Changed;
      17              : 
      18              : /**
      19              :  * @brief Compares basic file metadata fields (size, mtime, ctime).
      20              :  *
      21              :  * @param source       First stat structure
      22              :  * @param destination  Second stat structure
      23              :  *
      24              :  * @return Bitmask with IDENTICAL (0) when equal or a combination of:
      25              :  *         - SIZE_CHANGED
      26              :  *         - MODIFICATION_TIME_CHANGED
      27              :  *         - STATUS_CHANGED_TIME (uses ctime/status-change time)
      28              :  *         Returns FAILURE on invalid parameters.
      29              :  */
      30            8 : static int compare_file_metadata_equivalence(
      31              :         const struct stat *source,
      32              :         const struct stat *destination)
      33              : {
      34              :         /* Validate input parameters */
      35            8 :         if(NULL == source || NULL == destination)
      36              :         {
      37            0 :                 return(COMPARE_FAILED);
      38              :         }
      39              : 
      40            8 :         int changes = IDENTICAL;
      41              : 
      42              :         /* Size of file, in bytes.  */
      43            8 :         if(source->st_size != destination->st_size)
      44              :         {
      45            0 :                 changes |= SIZE_CHANGED;
      46              : 
      47              :         }
      48              : 
      49              :         /* Modified timestamp */
      50            8 :         if(!(source->st_mtim.tv_sec == destination->st_mtim.tv_sec &&
      51            8 :                 source->st_mtim.tv_nsec == destination->st_mtim.tv_nsec))
      52              :         {
      53            0 :                 changes |= MODIFICATION_TIME_CHANGED;
      54              : 
      55              :         }
      56              : 
      57              :         /* Time of last status change  */
      58            8 :         if(!(source->st_ctim.tv_sec == destination->st_ctim.tv_sec &&
      59            8 :                 source->st_ctim.tv_nsec == destination->st_ctim.tv_nsec))
      60              :         {
      61            0 :                 changes |= STATUS_CHANGED_TIME;
      62              : 
      63              :         }
      64              : 
      65            8 :         return(changes);
      66              : }
      67              : 
      68              : /**
      69              :  * @brief Prints all fields of the stat structure
      70              :  *
      71              :  * @param[in] st Pointer to the stat structure to print
      72              :  * @return Return Status of the operation
      73              :  */
      74            0 : Return print_stat(const struct stat *st)
      75              : {
      76            0 :         Return status = SUCCESS;
      77              :         char time_str[20]; /* "YYYY-MM-DD HH:MM:SS" + NUL */
      78              :         struct tm *tm_info;
      79              : 
      80            0 :         if(SUCCESS == status)
      81              :         {
      82            0 :                 if(NULL == st)
      83              :                 {
      84            0 :                         status = FAILURE;
      85              :                 }
      86              :         }
      87              : 
      88            0 :         if(SUCCESS == status)
      89              :         {
      90            0 :                 echo(STDERR,"----------------\n");
      91            0 :                 echo(STDERR,"File information:\n");
      92            0 :                 echo(STDERR,"Device ID: %lu\n",(unsigned long)st->st_dev);
      93            0 :                 echo(STDERR,"Inode number: %lu\n",(unsigned long)st->st_ino);
      94            0 :                 echo(STDERR,"Mode: %o (octal)\n",(unsigned int)st->st_mode);
      95            0 :                 echo(STDERR,"Hard links: %lu\n",(unsigned long)st->st_nlink);
      96            0 :                 echo(STDERR,"User ID: %u\n",st->st_uid);
      97            0 :                 echo(STDERR,"Group ID: %u\n",st->st_gid);
      98            0 :                 echo(STDERR,"Device ID (if special file): %lu\n",(unsigned long)st->st_rdev);
      99            0 :                 echo(STDERR,"Total size: %ld bytes\n",(long)st->st_size);
     100            0 :                 echo(STDERR,"Block size: %ld\n",(long)st->st_blksize);
     101            0 :                 echo(STDERR,"Number of blocks: %ld\n",(long)st->st_blocks);
     102              : 
     103              :                 // Access time
     104            0 :                 tm_info = localtime(&st->st_atim.tv_sec);
     105            0 :                 strftime(time_str,sizeof(time_str),"%Y-%m-%d %H:%M:%S",tm_info);
     106            0 :                 echo(STDERR,"Last access: %s.%09ld\n",time_str,st->st_atim.tv_nsec);
     107              : 
     108              :                 // Modification time
     109            0 :                 tm_info = localtime(&st->st_mtim.tv_sec);
     110            0 :                 strftime(time_str,sizeof(time_str),"%Y-%m-%d %H:%M:%S",tm_info);
     111            0 :                 echo(STDERR,"Last modification: %s.%09ld\n",time_str,st->st_mtim.tv_nsec);
     112              : 
     113              :                 // Status change time
     114            0 :                 tm_info = localtime(&st->st_ctim.tv_sec);
     115            0 :                 strftime(time_str,sizeof(time_str),"%Y-%m-%d %H:%M:%S",tm_info);
     116            0 :                 echo(STDERR,"Last status change: %s.%09ld\n",time_str,st->st_ctim.tv_nsec);
     117              : 
     118              :                 // Print file type
     119            0 :                 echo(STDERR,"File type: ");
     120              : 
     121            0 :                 switch(st->st_mode & S_IFMT)
     122              :                 {
     123            0 :                         case S_IFBLK:
     124            0 :                                 echo(STDERR,"block device\n");
     125            0 :                                 break;
     126            0 :                         case S_IFCHR:
     127            0 :                                 echo(STDERR,"character device\n");
     128            0 :                                 break;
     129            0 :                         case S_IFDIR:
     130            0 :                                 echo(STDERR,"directory\n");
     131            0 :                                 break;
     132            0 :                         case S_IFIFO:
     133            0 :                                 echo(STDERR,"FIFO/pipe\n");
     134            0 :                                 break;
     135            0 :                         case S_IFLNK:
     136            0 :                                 echo(STDERR,"symlink\n");
     137            0 :                                 break;
     138            0 :                         case S_IFREG:
     139            0 :                                 echo(STDERR,"regular file\n");
     140            0 :                                 break;
     141            0 :                         case S_IFSOCK:
     142            0 :                                 echo(STDERR,"socket\n");
     143            0 :                                 break;
     144            0 :                         default:
     145            0 :                                 echo(STDERR,"unknown\n");
     146            0 :                                 break;
     147              :                 }
     148              : 
     149              :                 // Print permissions
     150            0 :                 echo(STDERR,"Permissions: ");
     151            0 :                 echo(STDERR,(st->st_mode & S_IRUSR) ? "r" : "-");
     152            0 :                 echo(STDERR,(st->st_mode & S_IWUSR) ? "w" : "-");
     153            0 :                 echo(STDERR,(st->st_mode & S_IXUSR) ? "x" : "-");
     154            0 :                 echo(STDERR,(st->st_mode & S_IRGRP) ? "r" : "-");
     155            0 :                 echo(STDERR,(st->st_mode & S_IWGRP) ? "w" : "-");
     156            0 :                 echo(STDERR,(st->st_mode & S_IXGRP) ? "x" : "-");
     157            0 :                 echo(STDERR,(st->st_mode & S_IROTH) ? "r" : "-");
     158            0 :                 echo(STDERR,(st->st_mode & S_IWOTH) ? "w" : "-");
     159            0 :                 echo(STDERR,(st->st_mode & S_IXOTH) ? "x" : "-");
     160            0 :                 echo(STDERR,"\n");
     161              :         }
     162              : 
     163            0 :         return(status);
     164              : }
     165              : 
     166              : /**
     167              :  * @brief Reports whether two stat structures describe the same file metadata.
     168              :  *
     169              :  * Prints both structures to STDERR when any tracked field differs.
     170              :  *
     171              :  * @param stat1 First stat structure
     172              :  * @param stat2 Second stat structure
     173              :  * @return SUCCESS when metadata matches; FAILURE otherwise
     174              :  */
     175            8 : Return check_file_identity(
     176              :         const struct stat *stat1,
     177              :         const struct stat *stat2)
     178              : {
     179            8 :         Return status = SUCCESS;
     180              : 
     181            8 :         if(IDENTICAL != compare_file_metadata_equivalence(stat1,stat2))
     182              :         {
     183            0 :                 print_stat(stat1);
     184            0 :                 print_stat(stat2);
     185            0 :                 status = FAILURE;
     186              :         }
     187              : 
     188            8 :         return(status);
     189              : }
        

Generated by: LCOV version 2.0-1