implement md5 convenience file and string wrappers. Modify readfile to support this
This commit is contained in:
parent
b6f3c99c1a
commit
ee63f15526
@ -1,7 +1,8 @@
|
||||
depth = ..
|
||||
include $(depth)/mk/sysconf
|
||||
|
||||
PROGS = trreadfile trfileudi trconftree wipedir smallut trfstreewalk trpathut \
|
||||
PROGS = trmd5 trreadfile trfileudi trconftree wipedir smallut \
|
||||
trfstreewalk trpathut \
|
||||
transcode trbase64 \
|
||||
trmimeparse trexecmd utf8iter idfile
|
||||
|
||||
@ -25,6 +26,13 @@ trreadfile.o : readfile.cpp readfile.h
|
||||
$(CXX) -o trreadfile.o -c $(ALL_CXXFLAGS) \
|
||||
-DTEST_READFILE readfile.cpp
|
||||
|
||||
MD5_OBJS= trmd5.o md5.o $(BIGLIB)
|
||||
trmd5 : $(MD5_OBJS)
|
||||
$(CXX) -o trmd5 $(MD5_OBJS) $(LIBICONV) $(LIBSYS)
|
||||
trmd5.o : md5.cpp md5.h
|
||||
$(CXX) -o trmd5.o -c $(ALL_CXXFLAGS) \
|
||||
-DTEST_MD5 md5.cpp
|
||||
|
||||
PATHUT_OBJS= trpathut.o $(BIGLIB)
|
||||
trpathut : $(PATHUT_OBJS)
|
||||
$(CXX) $(ALL_CXXFLAGS) -o trpathut $(PATHUT_OBJS) $(LIBICONV)
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
* This code is the same as the code published by RSA Inc. It has been
|
||||
* edited for clarity and style only.
|
||||
*/
|
||||
|
||||
#ifndef TEST_MD5
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
@ -316,3 +316,129 @@ MD5Transform (md5uint32 state[4], const unsigned char block[64])
|
||||
/* Zeroize sensitive information. */
|
||||
memset ((void *)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
/*************** Convenience / utilities */
|
||||
void MD5Final(string &digest, MD5_CTX *context)
|
||||
{
|
||||
unsigned char d[16];
|
||||
MD5Final (d, context);
|
||||
digest.assign((const char *)d, 16);
|
||||
}
|
||||
|
||||
string& MD5String(const string& data, string& digest)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (const unsigned char*)data.c_str(), data.length());
|
||||
MD5Final(digest, &ctx);
|
||||
return digest;
|
||||
}
|
||||
|
||||
string& MD5HexPrint(const string& digest, string &out)
|
||||
{
|
||||
out.erase();
|
||||
out.reserve(33);
|
||||
static const char hex[]="0123456789abcdef";
|
||||
const unsigned char *hash = (const unsigned char *)digest.c_str();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
out.append(1, hex[hash[i] >> 4]);
|
||||
out.append(1, hex[hash[i] & 0x0f]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
string& MD5HexScan(const string& xdigest, string& digest)
|
||||
{
|
||||
digest.erase();
|
||||
if (xdigest.length() != 32) {
|
||||
return digest;
|
||||
}
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
unsigned int val;
|
||||
if (sscanf(xdigest.c_str() + 2*i, "%2x", &val) != 1) {
|
||||
digest.erase();
|
||||
return digest;
|
||||
}
|
||||
digest.append(1, (unsigned char)val);
|
||||
}
|
||||
return digest;
|
||||
}
|
||||
|
||||
#include "readfile.h"
|
||||
class FileScanMd5 : public FileScanDo {
|
||||
public:
|
||||
FileScanMd5(string& d) : digest(d) {}
|
||||
virtual bool init(unsigned int size, string *reason)
|
||||
{
|
||||
MD5Init(&ctx);
|
||||
return true;
|
||||
}
|
||||
virtual bool data(const char *buf, int cnt, string* reason)
|
||||
{
|
||||
MD5Update(&ctx, (const unsigned char*)buf, cnt);
|
||||
return true;
|
||||
}
|
||||
string &digest;
|
||||
MD5_CTX ctx;
|
||||
};
|
||||
bool MD5File(const string& filename, string &digest, string *reason)
|
||||
{
|
||||
FileScanMd5 md5er(digest);
|
||||
if (!file_scan(filename, &md5er, reason))
|
||||
return false;
|
||||
// We happen to know that digest and md5er.digest are the same object
|
||||
MD5Final(md5er.digest, &md5er.ctx);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
// Test driver
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "md5.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *thisprog;
|
||||
static char usage [] =
|
||||
"trmd5 filename\n\n"
|
||||
;
|
||||
static void
|
||||
Usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
thisprog = argv[0];
|
||||
argc--; argv++;
|
||||
|
||||
if (argc != 1)
|
||||
Usage();
|
||||
string filename = *argv++;argc--;
|
||||
|
||||
string reason, digest;
|
||||
if (!MD5File(filename, digest, &reason)) {
|
||||
cerr << reason << endl;
|
||||
exit(1);
|
||||
} else {
|
||||
string hex;
|
||||
cout << "MD5 (" << filename << ") = " << MD5HexPrint(digest, hex) << endl;
|
||||
|
||||
string digest1;
|
||||
MD5HexScan(hex, digest1);
|
||||
if (digest1.compare(digest)) {
|
||||
cout << "MD5HexScan Failure" << endl;
|
||||
cout << MD5HexPrint(digest, hex) << " " << digest.length() << " -> "
|
||||
<< MD5HexPrint(digest1, hex) << " " << digest1.length() << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -26,8 +26,7 @@ These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Base functions from original file */
|
||||
/* MD5 context. */
|
||||
typedef struct MD5Context {
|
||||
unsigned int state[4]; /* state (ABCD) */
|
||||
@ -35,9 +34,16 @@ typedef struct MD5Context {
|
||||
unsigned char buffer[64]; /* input buffer */
|
||||
} MD5_CTX;
|
||||
|
||||
void MD5Init (MD5_CTX *);
|
||||
void MD5Update (MD5_CTX *, const unsigned char *, unsigned int);
|
||||
void MD5Final (unsigned char [16], MD5_CTX *);
|
||||
}
|
||||
extern void MD5Init (MD5_CTX *);
|
||||
extern void MD5Update (MD5_CTX *, const unsigned char *, unsigned int);
|
||||
extern void MD5Final (unsigned char [16], MD5_CTX *);
|
||||
|
||||
/* Convenience / utilities */
|
||||
#include <string>
|
||||
using std::string;
|
||||
extern void MD5Final(string& digest, MD5_CTX *);
|
||||
extern bool MD5File(const string& filename, string& digest, string *reason);
|
||||
extern string& MD5String(const string& data, string& digest);
|
||||
extern string& MD5HexPrint(const string& digest, string& xdigest);
|
||||
extern string& MD5HexScan(const string& xdigest, string& digest);
|
||||
#endif /* _MD5_H_ */
|
||||
|
||||
@ -40,27 +40,53 @@ using std::string;
|
||||
|
||||
static void caterrno(string *reason, const char *what)
|
||||
{
|
||||
#define ERRBUFSZ 200
|
||||
char errbuf[ERRBUFSZ];
|
||||
if (reason) {
|
||||
*reason += "file_to_string: ";
|
||||
*reason += what;
|
||||
*reason += ": ";
|
||||
reason->append("file_to_string: ");
|
||||
reason->append(what);
|
||||
reason->append(": ");
|
||||
#ifdef sun
|
||||
// Note: sun strerror is noted mt-safe ??
|
||||
*reason += strerror(errno);
|
||||
reason->append(strerror(errno));
|
||||
#else
|
||||
#define ERRBUFSZ 200
|
||||
char errbuf[ERRBUFSZ];
|
||||
strerror_r(errno, errbuf, ERRBUFSZ);
|
||||
*reason += errbuf;
|
||||
reason->append(errbuf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Note: the fstat() + reserve() calls divide cpu usage almost by 2
|
||||
class FileToString : public FileScanDo {
|
||||
public:
|
||||
FileToString(string& data) : m_data(data) {}
|
||||
string& m_data;
|
||||
bool init(unsigned int size, string *reason) {
|
||||
if (size > 0)
|
||||
m_data.reserve(size);
|
||||
return true;
|
||||
}
|
||||
bool data(const char *buf, int cnt, string *reason) {
|
||||
try {
|
||||
m_data.append(buf, cnt);
|
||||
} catch (...) {
|
||||
caterrno(reason, "append");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool file_to_string(const string &fn, string &data, string *reason)
|
||||
{
|
||||
FileToString accum(data);
|
||||
return file_scan(fn, &accum, reason);
|
||||
}
|
||||
|
||||
// Note: the fstat() + reserve() (in init()) calls divide cpu usage almost by 2
|
||||
// on both linux i586 and macosx (compared to just append())
|
||||
// Also tried a version with mmap, but it's actually slower on the mac and not
|
||||
// faster on linux.
|
||||
bool file_to_string(const string &fn, string &data, string *reason)
|
||||
bool file_scan(const string &fn, FileScanDo* doer, string *reason)
|
||||
{
|
||||
bool ret = false;
|
||||
bool noclosing = true;
|
||||
@ -72,19 +98,16 @@ bool file_to_string(const string &fn, string &data, string *reason)
|
||||
// If we have a file name, open it, else use stdin.
|
||||
if (!fn.empty()) {
|
||||
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
|
||||
if (fd < 0
|
||||
#if 1
|
||||
|| fstat(fd, &st) < 0
|
||||
#endif
|
||||
) {
|
||||
if (fd < 0 || fstat(fd, &st) < 0) {
|
||||
caterrno(reason, "open/stat");
|
||||
return false;
|
||||
}
|
||||
noclosing = false;
|
||||
}
|
||||
if (st.st_size > 0)
|
||||
data.reserve(st.st_size+1);
|
||||
|
||||
doer->init(st.st_size+1, reason);
|
||||
else
|
||||
doer->init(0, reason);
|
||||
char buf[4096];
|
||||
for (;;) {
|
||||
int n = read(fd, buf, 4096);
|
||||
@ -95,10 +118,7 @@ bool file_to_string(const string &fn, string &data, string *reason)
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
try {
|
||||
data.append(buf, n);
|
||||
} catch (...) {
|
||||
caterrno(reason, "append");
|
||||
if (!doer->data(buf, n, reason)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -206,7 +226,7 @@ int main(int argc, const char **argv)
|
||||
} else if (S_ISREG(st.st_mode)) {
|
||||
string s, reason;
|
||||
if (!file_to_string(top, s, &reason)) {
|
||||
cerr << reason;
|
||||
cerr << reason << endl;
|
||||
exit(1);
|
||||
} else {
|
||||
cout << s;
|
||||
|
||||
@ -19,12 +19,21 @@
|
||||
/* @(#$Id: readfile.h,v 1.3 2007-06-02 08:30:42 dockes Exp $ (C) 2004 J.F.Dockes */
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
/**
|
||||
* Read whole file into string.
|
||||
* @return true for ok, false else
|
||||
*/
|
||||
bool file_to_string(const std::string &filename, std::string &data,
|
||||
std::string *reason = 0);
|
||||
bool file_to_string(const string &filename, string &data, string *reason = 0);
|
||||
|
||||
class FileScanDo {
|
||||
public:
|
||||
virtual ~FileScanDo() {}
|
||||
virtual bool init(unsigned int size, string *reason) = 0;
|
||||
virtual bool data(const char *buf, int cnt, string* reason) = 0;
|
||||
};
|
||||
bool file_scan(const std::string &filename, FileScanDo* doer,
|
||||
std::string *reason = 0);
|
||||
|
||||
#endif /* _READFILE_H_INCLUDED_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user