diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2005-01-13T17·39+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2005-01-13T17·39+0000 |
commit | 7e8961f72056f53ccf78eba0ee8c240bc2310ab8 (patch) | |
tree | f4ae8ee014f3d86aa9ec1706d1aa9e83c2329a73 /src/libutil/hash.cc | |
parent | 73992371a3bc16b27b22e53d5f7ae600dea9cf60 (diff) |
* Added SHA-1 support. `nix-hash' now has an option `--type sha1' to
select SHA-1 hashing.
Diffstat (limited to 'src/libutil/hash.cc')
-rw-r--r-- | src/libutil/hash.cc | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 1a44c85341e4..46334ad820d7 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -2,17 +2,24 @@ extern "C" { #include "md5.h" +#include "sha1.h" } #include "hash.hh" #include "archive.hh" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + + Hash::Hash(HashType type) { this->type = type; if (type == htMD5) hashSize = md5HashSize; else if (type == htSHA1) hashSize = sha1HashSize; + else throw Error("unknown hash type"); memset(hash, 0, hashSize); } @@ -85,44 +92,90 @@ bool isHash(const string & s) } -Hash hashString(const string & s) +struct Ctx { - Hash hash(htMD5); - md5_buffer(s.c_str(), s.length(), hash.hash); + md5_ctx md5; + sha_ctx sha1; +}; + + +static void start(HashType ht, Ctx & ctx) +{ + if (ht == htMD5) md5_init_ctx(&ctx.md5); + else if (ht == htSHA1) sha_init(&ctx.sha1); +} + + +static void update(HashType ht, Ctx & ctx, + const unsigned char * bytes, unsigned int len) +{ + if (ht == htMD5) md5_process_bytes(bytes, len, &ctx.md5); + else if (ht == htSHA1) sha_update(&ctx.sha1, bytes, len); +} + + +static void finish(HashType ht, Ctx & ctx, unsigned char * hash) +{ + if (ht == htMD5) md5_finish_ctx(&ctx.md5, hash); + else if (ht == htSHA1) { + sha_final(&ctx.sha1); + sha_digest(&ctx.sha1, hash); + } +} + + +Hash hashString(const string & s, HashType ht) +{ + Ctx ctx; + Hash hash(ht); + start(ht, ctx); + update(ht, ctx, (const unsigned char *) s.c_str(), s.length()); + finish(ht, ctx, hash.hash); return hash; } -Hash hashFile(const Path & path) +Hash hashFile(const Path & path, HashType ht) { - Hash hash(htMD5); - FILE * file = fopen(path.c_str(), "rb"); - if (!file) - throw SysError(format("file `%1%' does not exist") % path); - int err = md5_stream(file, hash.hash); - fclose(file); - if (err) throw SysError(format("cannot hash file `%1%'") % path); + Ctx ctx; + Hash hash(ht); + start(ht, ctx); + + AutoCloseFD fd = open(path.c_str(), O_RDONLY); + if (fd == -1) throw SysError(format("opening file `%1%'") % path); + + unsigned char buf[8192]; + ssize_t n; + while ((n = read(fd, buf, sizeof(buf)))) { + checkInterrupt(); + if (n == -1) throw SysError(format("reading file `%1%'") % path); + update(ht, ctx, buf, n); + } + + finish(ht, ctx, hash.hash); return hash; } struct HashSink : DumpSink { - struct md5_ctx ctx; + HashType ht; + Ctx ctx; virtual void operator () (const unsigned char * data, unsigned int len) { - md5_process_bytes(data, len, &ctx); + update(ht, ctx, data, len); } }; -Hash hashPath(const Path & path) +Hash hashPath(const Path & path, HashType ht) { - Hash hash(htMD5); HashSink sink; - md5_init_ctx(&sink.ctx); + sink.ht = ht; + Hash hash(ht); + start(ht, sink.ctx); dumpPath(path, sink); - md5_finish_ctx(&sink.ctx, hash.hash); + finish(ht, sink.ctx, hash.hash); return hash; } |