File indexing completed on 2026-04-09 07:49:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "SDigest.hh"
0021 #include "SSys.hh"
0022
0023 #include <cstdio>
0024 #include <cstdlib>
0025 #include <cstring>
0026 #include <cassert>
0027
0028 #include <iostream>
0029
0030 #include "SLOG.hh"
0031
0032 const plog::Severity SDigest::LEVEL = SLOG::EnvLevel("SDigest", "DEBUG") ;
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 std::string SDigest::DigestPathInByteRange(const char* path, int i0, int i1, unsigned bufsize)
0064 {
0065 LOG(LEVEL)
0066 << " path " << path
0067 << " i0 " << i0
0068 << " i1 " << i1
0069 << " bufsize " << bufsize
0070 ;
0071
0072 FILE* fp = fopen(path, "rb");
0073 if (fp == NULL)
0074 {
0075 LOG(error) << "failed to open path [" << path << "]" ;
0076 return "" ;
0077 }
0078 SDigest dig ;
0079 char* data = new char[bufsize] ;
0080 int bytes ;
0081
0082 int beg = 0 ;
0083 int end = 0 ;
0084 int tot = 0 ;
0085
0086 assert( i1 > i0 ) ;
0087
0088 while ((bytes = fread (data, 1, bufsize, fp)) != 0)
0089 {
0090 end = beg + bytes ;
0091
0092 bool starts = i0 >= beg && i0 < end ;
0093 bool ends = i1 <= end ;
0094
0095 int idx0(-1) ;
0096 int idx1(-1) ;
0097
0098 if( starts && ends )
0099 {
0100 idx0 = i0 - beg ;
0101 idx1 = i1 - beg ;
0102 }
0103 else if( starts && !ends )
0104 {
0105 idx0 = i0 - beg ;
0106 idx1 = bytes ;
0107 }
0108 else if( !starts && ends )
0109 {
0110 idx0 = 0 ;
0111 idx1 = i1 - beg ;
0112 }
0113 else if( !starts && !ends && tot > 0 )
0114 {
0115 idx0 = 0 ;
0116 idx1 = bytes ;
0117 }
0118
0119
0120 int nup = idx1 - idx0 ;
0121 bool update = idx0 > -1 && idx1 > -1 ;
0122
0123 std::string x = update ? SSys::xxd( data+idx0, nup ) : "-" ;
0124
0125 LOG(LEVEL)
0126 << " bytes " << std::setw(8) << bytes
0127 << " beg " << std::setw(8) << beg
0128 << " end " << std::setw(8) << end
0129 << " idx0 " << std::setw(8) << idx0
0130 << " idx1 " << std::setw(8) << idx1
0131 << " nup " << std::setw(8) << nup
0132 << ( starts ? " S " : " ")
0133 << ( ends ? " E " : " ")
0134 << ( update ? " U " : " ")
0135 << " x " << x
0136 ;
0137
0138 if(update)
0139 {
0140 dig.update(data+idx0, nup );
0141 tot += nup ;
0142 }
0143
0144 if( ends ) break ;
0145
0146 beg += bytes ;
0147 }
0148
0149 delete[] data ;
0150
0151 std::string sdig = dig.finalize();
0152 LOG(LEVEL) << " sdig " << sdig ;
0153 return sdig ;
0154 }
0155
0156
0157
0158 std::string SDigest::DigestPath(const char* path, unsigned bufsize)
0159 {
0160 FILE* fp = fopen(path, "rb");
0161 if (fp == NULL)
0162 {
0163 std::cerr << "failed to open path [" << path << "]" << std::endl ;
0164 return "" ;
0165 }
0166 SDigest dig ;
0167 char* data = new char[bufsize] ;
0168 int bytes ;
0169 while ((bytes = fread (data, 1, bufsize, fp)) != 0) dig.update(data, bytes);
0170
0171 delete[] data ;
0172 return dig.finalize();
0173 }
0174
0175
0176
0177
0178 #if defined(__GNUC__) || defined(__clang__)
0179 #pragma GCC diagnostic push
0180 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0181 #endif
0182
0183
0184
0185
0186 std::string SDigest::DigestPath2(const char* path)
0187 {
0188 int i;
0189 FILE* fp = fopen (path, "rb");
0190 MD5_CTX mdContext;
0191 int bytes;
0192 char data[8192];
0193
0194 if (fp == NULL) {
0195 printf ("%s can't be opened.\n", path);
0196 return "";
0197 }
0198
0199 MD5_Init (&mdContext);
0200 while ((bytes = fread (data, 1, 8192, fp)) != 0)
0201 MD5_Update (&mdContext, data, bytes);
0202
0203 fclose (fp);
0204
0205 assert( MD5_DIGEST_LENGTH == 16 );
0206 unsigned char digest[MD5_DIGEST_LENGTH];
0207 MD5_Final (digest,&mdContext);
0208 char *out = (char*)malloc(MD5_DIGEST_LENGTH*2+1);
0209 for(i = 0; i < MD5_DIGEST_LENGTH; i++) snprintf(&(out[i*2]), MD5_DIGEST_LENGTH*2, "%02x", (unsigned int)digest[i]);
0210 out[MD5_DIGEST_LENGTH*2] = '\0' ;
0211
0212 return out ;
0213 }
0214
0215
0216
0217
0218 char* md5digest_str2md5_monolithic(const char *buffer, int length)
0219 {
0220
0221
0222 MD5_CTX c;
0223 MD5_Init(&c);
0224
0225 const int blocksize = 512 ;
0226 while (length > 0)
0227 {
0228 if (length > blocksize) {
0229 MD5_Update(&c, buffer, blocksize);
0230 } else {
0231 MD5_Update(&c, buffer, length);
0232 }
0233 length -= blocksize ;
0234 buffer += blocksize ;
0235 }
0236
0237 unsigned char digest[16];
0238 MD5_Final(digest, &c);
0239
0240
0241 char *out = (char*)malloc(32+1);
0242 for (int n = 0; n < 16; ++n) snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
0243 out[32] = '\0' ;
0244 return out;
0245 }
0246
0247
0248 std::string SDigest::Buffer(const char *buffer, int length)
0249 {
0250 MD5_CTX c;
0251 MD5_Init(&c);
0252
0253 const int blocksize = 512 ;
0254 while (length > 0)
0255 {
0256 if (length > blocksize) {
0257 MD5_Update(&c, buffer, blocksize);
0258 } else {
0259 MD5_Update(&c, buffer, length);
0260 }
0261 length -= blocksize ;
0262 buffer += blocksize ;
0263 }
0264
0265 unsigned char digest[16];
0266 MD5_Final(digest, &c);
0267
0268
0269
0270 char buf[32+1] ;
0271 for (int n = 0; n < 16; ++n) std::snprintf( &buf[2*n], 32+1, "%02x", (unsigned int)digest[n]) ;
0272 buf[32] = '\0' ;
0273
0274 return std::string(buf, buf + 32);
0275 }
0276
0277 void md5digest_str2md5_update(MD5_CTX& ctx, char* buffer, int length)
0278 {
0279 const int blocksize = 512 ;
0280 while (length > 0)
0281 {
0282 if (length > blocksize) {
0283 MD5_Update(&ctx, buffer, blocksize);
0284 } else {
0285 MD5_Update(&ctx, buffer, length);
0286 }
0287 length -= blocksize ;
0288 buffer += blocksize ;
0289 }
0290 }
0291
0292 char* md5digest_str2md5_finalize( MD5_CTX& ctx )
0293 {
0294 unsigned char digest[16];
0295 MD5_Final(digest, &ctx);
0296
0297
0298 char *out = (char*)malloc(32+1);
0299 for (int n = 0; n < 16; ++n) snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
0300 out[32] = '\0' ;
0301 return out;
0302 }
0303
0304 char* md5digest_str2md5(char* buffer, int length)
0305 {
0306
0307
0308 MD5_CTX ctx;
0309 MD5_Init(&ctx);
0310
0311 md5digest_str2md5_update(ctx, buffer, length );
0312
0313 return md5digest_str2md5_finalize(ctx);
0314 }
0315
0316
0317 SDigest::SDigest()
0318 {
0319 MD5_Init(&m_ctx);
0320 }
0321
0322
0323 #if defined(__GNUC__) || defined(__clang__)
0324 #pragma GCC diagnostic pop
0325 #endif
0326
0327
0328
0329
0330
0331
0332
0333 const char* SDigest::hexchar = "0123456789abcdef" ;
0334
0335 bool SDigest::IsDigest(const char* s)
0336 {
0337 if( s == NULL ) return false ;
0338 if( strlen(s) != 32 ) return false ;
0339 for(int i=0 ; i < 32 ; i++ )
0340 {
0341 char c = *(s + i) ;
0342 if(strchr(hexchar,c) == NULL) return false ;
0343 }
0344 return true ;
0345 }
0346
0347
0348
0349
0350
0351
0352 SDigest::~SDigest()
0353 {
0354 }
0355
0356 void SDigest::update(const std::string& str)
0357 {
0358 update( (char*)str.c_str(), strlen(str.c_str()) );
0359 }
0360
0361 void SDigest::update(char* buffer, int length)
0362 {
0363 md5digest_str2md5_update(m_ctx, buffer, length );
0364 }
0365
0366 void SDigest::update_str(const char* str )
0367 {
0368 md5digest_str2md5_update(m_ctx, (char*)str, strlen(str) );
0369 }
0370
0371
0372 char* SDigest::finalize()
0373 {
0374 return md5digest_str2md5_finalize(m_ctx);
0375 }
0376
0377
0378
0379 std::string SDigest::md5digest( const char* buffer, int len )
0380 {
0381 char* out = md5digest_str2md5_monolithic(buffer, len);
0382 std::string digest(out);
0383 free(out);
0384 return digest;
0385 }
0386
0387 const char* SDigest::md5digest_( const char* buffer, int len )
0388 {
0389 return md5digest_str2md5_monolithic(buffer, len);
0390 }
0391
0392
0393 std::string SDigest::digest( void* buffer, int len )
0394 {
0395 SDigest dig ;
0396 dig.update( (char*)buffer, len );
0397 return dig.finalize();
0398 }
0399
0400 std::string SDigest::digest( std::vector<std::string>& ss)
0401 {
0402 SDigest dig ;
0403 for(unsigned i=0 ; i < ss.size() ; i++) dig.update( ss[i] ) ;
0404 return dig.finalize();
0405 }
0406
0407
0408 std::string SDigest::digest_skipdupe( std::vector<std::string>& ss)
0409 {
0410 SDigest dig ;
0411 for(unsigned i=0 ; i < ss.size() ; i++)
0412 {
0413 if( i > 0 && ss[i].compare(ss[i-1].c_str()) == 0 ) continue ;
0414 dig.update( ss[i] ) ;
0415 }
0416 return dig.finalize();
0417 }
0418