5959 * standard wildcarded ( ? / * style, NOT regex) exclusions.
6060 * - tries to play permissions and flags smart in regards to overwriting
6161 * schg files and doing related stuff.
62- * - Can do MD5 consistancy checks
62+ * - Can do checksum consistancy checks with any supported OpenSSL EVP
63+ * message digest
6364 * - Is able to do incremental mirroring/backups via hardlinks from
6465 * the 'previous' version (supplied with -H path).
6566 */
6667
6768#include "cpdup.h"
6869#include "hclink.h"
6970#include "hcproto.h"
71+ #include <ctype.h>
7072
7173#define HSIZE 8192
7274#define HMASK (HSIZE-1)
@@ -188,23 +190,43 @@ int64_t CountLinkedItems;
188190static struct HostConf SrcHost ;
189191static struct HostConf DstHost ;
190192
193+ #ifndef NOMD5
194+ const EVP_MD * CsumAlgo ;
195+ #endif
196+
191197int
192198main (int ac , char * * av )
193199{
194200 int i ;
201+ #ifndef NOMD5
202+ int len ;
203+ #endif
195204 int opt ;
196205 char * src = NULL ;
197206 char * dst = NULL ;
198207 char * ptr ;
199208 struct timeval start ;
200209 struct copy_info info ;
201210
211+ #ifndef NOMD5
212+ char * MD5AlgoStr ;
213+ char * MD5CacheFileStr ;
214+ const char * CsumAlgoStrArg = NULL ;
215+ const char * MD5CacheFileArg = NULL ;
216+ #endif
217+
202218 signal (SIGPIPE , SIG_IGN );
203219
204220 gettimeofday (& start , NULL );
205221 opterr = 0 ;
206- while ((opt = getopt (ac , av , ":CdF:fH:hIi:j:lM:mnoqRSs:uVvX:x" )) != -1 ) {
222+ while ((opt = getopt (ac , av , ":c: CdF:fH:hIi:j:lM:mnoqRSs:uVvX:x" )) != -1 ) {
207223 switch (opt ) {
224+ case 'c' :
225+ UseMD5Opt = 1 ;
226+ #ifndef NOMD5
227+ CsumAlgoStrArg = optarg ;
228+ #endif
229+ break ;
208230 case 'C' :
209231 CompressOpt = 1 ;
210232 break ;
@@ -241,11 +263,17 @@ main(int ac, char **av)
241263 break ;
242264 case 'M' :
243265 UseMD5Opt = 1 ;
244- MD5CacheFile = optarg ;
266+ if (strnlen (optarg , PATH_MAX ) == PATH_MAX )
267+ fatal ("Cache file string too long" );
268+ #ifndef NOMD5
269+ MD5CacheFileArg = optarg ;
270+ #endif
245271 break ;
246272 case 'm' :
247273 UseMD5Opt = 1 ;
248- MD5CacheFile = ".MD5.CHECKSUMS" ;
274+ #ifndef NOMD5
275+ CsumAlgoStrArg = "MD5" ;
276+ #endif
249277 break ;
250278 case 'n' :
251279 NotForRealOpt = 1 ;
@@ -303,6 +331,27 @@ main(int ac, char **av)
303331 if (ac > 2 )
304332 fatal ("too many arguments" );
305333
334+ #ifndef NOMD5
335+ if (UseMD5Opt ) {
336+ if (CsumAlgoStrArg == NULL )
337+ CsumAlgoStrArg = "MD5" ;
338+ CsumAlgo = EVP_get_digestbyname (CsumAlgoStrArg );
339+ if (CsumAlgo == NULL )
340+ fatal ("Unknown digest algorithm: %s" , CsumAlgoStrArg );
341+ len = strlen (CsumAlgoStrArg );
342+ CsumAlgoStr = malloc (len + 1 );
343+ for (i = 0 ; i < len ; i ++ )
344+ CsumAlgoStr [i ] = toupper (CsumAlgoStrArg [i ]);
345+ CsumAlgoStr [i ] = '\0' ;
346+ if (MD5CacheFileArg == NULL ) {
347+ if (asprintf (& MD5CacheFileStr , ".%s.CHECKSUMS" , CsumAlgoStr ) < 0 )
348+ fatal ("Memory allocation error\n" );
349+ } else
350+ MD5CacheFileStr = strdup (MD5CacheFileArg );
351+ MD5CacheFile = MD5CacheFileStr ;
352+ }
353+ #endif
354+
306355 /*
307356 * If we are told to go into slave mode, run the HC protocol
308357 */
@@ -320,7 +369,7 @@ main(int ac, char **av)
320369 SrcHost .host = src ;
321370 src = ptr ;
322371 if (UseMD5Opt )
323- fatal ("The MD5 options are not currently supported for remote sources" );
372+ fatal ("The checksum options are not currently supported for remote sources" );
324373 if (hc_connect (& SrcHost , ReadOnlyOpt ) < 0 )
325374 exit (1 );
326375 } else {
@@ -339,8 +388,8 @@ main(int ac, char **av)
339388 }
340389
341390 /*
342- * dst may be NULL only if -m option is specified,
343- * which forces an update of the MD5 checksums
391+ * dst may be NULL only if -c checksum or - m option is specified,
392+ * which forces an update of the checksums
344393 */
345394 if (dst == NULL && UseMD5Opt == 0 ) {
346395 fatal (NULL );
@@ -830,7 +879,7 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
830879 OwnerMatch (stat1 , & st2 )
831880#ifndef NOMD5
832881 && (UseMD5Opt == 0 || !S_ISREG (stat1 -> st_mode ) ||
833- (mres = md5_check (spath , dpath )) == 0 )
882+ (mres = md5_check (CsumAlgo , spath , dpath )) == 0 )
834883#endif
835884 && (ValidateOpt == 0 || !S_ISREG (stat1 -> st_mode ) ||
836885 validate_check (spath , dpath ) == 0 )
@@ -858,7 +907,7 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
858907 if (VerboseOpt >= 3 ) {
859908#ifndef NOMD5
860909 if (UseMD5Opt ) {
861- logstd ("%-32s md5 -nochange" ,
910+ logstd ("%-32s checksum -nochange" ,
862911 (dpath ? dpath : spath ));
863912 } else
864913#endif
@@ -1063,22 +1112,22 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
10631112 }
10641113 } else if (dpath == NULL ) {
10651114 /*
1066- * If dpath is NULL, we are just updating the MD5
1115+ * If dpath is NULL, we are just updating the checksum
10671116 */
10681117#ifndef NOMD5
10691118 if (UseMD5Opt && S_ISREG (stat1 -> st_mode )) {
1070- mres = md5_update (spath );
1119+ mres = md5_update (CsumAlgo , spath );
10711120
10721121 if (mres < 0 ) {
1073- logerr ("%-32s md5 -CHECK-FAILED\n" , spath );
1122+ logerr ("%-32s checksum -CHECK-FAILED\n" , spath );
10741123 } else {
10751124 if (VerboseOpt > 1 ) {
10761125 if (mres > 0 )
1077- logstd ("%-32s md5 -update\n" , spath );
1126+ logstd ("%-32s checksum -update\n" , spath );
10781127 else
1079- logstd ("%-32s md5 -ok\n" , spath );
1128+ logstd ("%-32s checksum -ok\n" , spath );
10801129 } else if (!QuietOpt && mres > 0 ) {
1081- logstd ("%-32s md5 -update\n" , spath );
1130+ logstd ("%-32s checksum -update\n" , spath );
10821131 }
10831132 }
10841133 }
@@ -1099,7 +1148,7 @@ DoCopy(copy_info_t info, struct stat *stat1, int depth)
10991148 * Handle check failure message.
11001149 */
11011150 if (mres < 0 )
1102- logerr ("%-32s md5 -CHECK-FAILED\n" , (dpath ) ? dpath : spath );
1151+ logerr ("%-32s checksum -CHECK-FAILED\n" , (dpath ) ? dpath : spath );
11031152#endif
11041153
11051154 /*
0 commit comments