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 = ..
|
depth = ..
|
||||||
include $(depth)/mk/sysconf
|
include $(depth)/mk/sysconf
|
||||||
|
|
||||||
PROGS = trreadfile trfileudi trconftree wipedir smallut trfstreewalk trpathut \
|
PROGS = trmd5 trreadfile trfileudi trconftree wipedir smallut \
|
||||||
|
trfstreewalk trpathut \
|
||||||
transcode trbase64 \
|
transcode trbase64 \
|
||||||
trmimeparse trexecmd utf8iter idfile
|
trmimeparse trexecmd utf8iter idfile
|
||||||
|
|
||||||
@ -25,6 +26,13 @@ trreadfile.o : readfile.cpp readfile.h
|
|||||||
$(CXX) -o trreadfile.o -c $(ALL_CXXFLAGS) \
|
$(CXX) -o trreadfile.o -c $(ALL_CXXFLAGS) \
|
||||||
-DTEST_READFILE readfile.cpp
|
-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)
|
PATHUT_OBJS= trpathut.o $(BIGLIB)
|
||||||
trpathut : $(PATHUT_OBJS)
|
trpathut : $(PATHUT_OBJS)
|
||||||
$(CXX) $(ALL_CXXFLAGS) -o trpathut $(PATHUT_OBJS) $(LIBICONV)
|
$(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
|
* This code is the same as the code published by RSA Inc. It has been
|
||||||
* edited for clarity and style only.
|
* edited for clarity and style only.
|
||||||
*/
|
*/
|
||||||
|
#ifndef TEST_MD5
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
@ -316,3 +316,129 @@ MD5Transform (md5uint32 state[4], const unsigned char block[64])
|
|||||||
/* Zeroize sensitive information. */
|
/* Zeroize sensitive information. */
|
||||||
memset ((void *)x, 0, sizeof (x));
|
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.
|
documentation and/or software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
/* Base functions from original file */
|
||||||
|
|
||||||
/* MD5 context. */
|
/* MD5 context. */
|
||||||
typedef struct MD5Context {
|
typedef struct MD5Context {
|
||||||
unsigned int state[4]; /* state (ABCD) */
|
unsigned int state[4]; /* state (ABCD) */
|
||||||
@ -35,9 +34,16 @@ typedef struct MD5Context {
|
|||||||
unsigned char buffer[64]; /* input buffer */
|
unsigned char buffer[64]; /* input buffer */
|
||||||
} MD5_CTX;
|
} MD5_CTX;
|
||||||
|
|
||||||
void MD5Init (MD5_CTX *);
|
extern void MD5Init (MD5_CTX *);
|
||||||
void MD5Update (MD5_CTX *, const unsigned char *, unsigned int);
|
extern void MD5Update (MD5_CTX *, const unsigned char *, unsigned int);
|
||||||
void MD5Final (unsigned char [16], MD5_CTX *);
|
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_ */
|
#endif /* _MD5_H_ */
|
||||||
|
|||||||
@ -40,27 +40,53 @@ using std::string;
|
|||||||
|
|
||||||
static void caterrno(string *reason, const char *what)
|
static void caterrno(string *reason, const char *what)
|
||||||
{
|
{
|
||||||
#define ERRBUFSZ 200
|
|
||||||
char errbuf[ERRBUFSZ];
|
|
||||||
if (reason) {
|
if (reason) {
|
||||||
*reason += "file_to_string: ";
|
reason->append("file_to_string: ");
|
||||||
*reason += what;
|
reason->append(what);
|
||||||
*reason += ": ";
|
reason->append(": ");
|
||||||
#ifdef sun
|
#ifdef sun
|
||||||
// Note: sun strerror is noted mt-safe ??
|
// Note: sun strerror is noted mt-safe ??
|
||||||
*reason += strerror(errno);
|
reason->append(strerror(errno));
|
||||||
#else
|
#else
|
||||||
|
#define ERRBUFSZ 200
|
||||||
|
char errbuf[ERRBUFSZ];
|
||||||
strerror_r(errno, errbuf, ERRBUFSZ);
|
strerror_r(errno, errbuf, ERRBUFSZ);
|
||||||
*reason += errbuf;
|
reason->append(errbuf);
|
||||||
#endif
|
#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())
|
// 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
|
// Also tried a version with mmap, but it's actually slower on the mac and not
|
||||||
// faster on linux.
|
// 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 ret = false;
|
||||||
bool noclosing = true;
|
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 we have a file name, open it, else use stdin.
|
||||||
if (!fn.empty()) {
|
if (!fn.empty()) {
|
||||||
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
|
fd = open(fn.c_str(), O_RDONLY|O_STREAMING);
|
||||||
if (fd < 0
|
if (fd < 0 || fstat(fd, &st) < 0) {
|
||||||
#if 1
|
|
||||||
|| fstat(fd, &st) < 0
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
caterrno(reason, "open/stat");
|
caterrno(reason, "open/stat");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
noclosing = false;
|
noclosing = false;
|
||||||
}
|
}
|
||||||
if (st.st_size > 0)
|
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];
|
char buf[4096];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int n = read(fd, buf, 4096);
|
int n = read(fd, buf, 4096);
|
||||||
@ -95,10 +118,7 @@ bool file_to_string(const string &fn, string &data, string *reason)
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
try {
|
if (!doer->data(buf, n, reason)) {
|
||||||
data.append(buf, n);
|
|
||||||
} catch (...) {
|
|
||||||
caterrno(reason, "append");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,7 +226,7 @@ int main(int argc, const char **argv)
|
|||||||
} else if (S_ISREG(st.st_mode)) {
|
} else if (S_ISREG(st.st_mode)) {
|
||||||
string s, reason;
|
string s, reason;
|
||||||
if (!file_to_string(top, s, &reason)) {
|
if (!file_to_string(top, s, &reason)) {
|
||||||
cerr << reason;
|
cerr << reason << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
} else {
|
} else {
|
||||||
cout << s;
|
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 */
|
/* @(#$Id: readfile.h,v 1.3 2007-06-02 08:30:42 dockes Exp $ (C) 2004 J.F.Dockes */
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
using std::string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read whole file into string.
|
* Read whole file into string.
|
||||||
* @return true for ok, false else
|
* @return true for ok, false else
|
||||||
*/
|
*/
|
||||||
bool file_to_string(const std::string &filename, std::string &data,
|
bool file_to_string(const string &filename, string &data, string *reason = 0);
|
||||||
std::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_ */
|
#endif /* _READFILE_H_INCLUDED_ */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user