#!/usr/local/bin/cz -- # hash-link: symlink files to their hash use openssl/sha.h use openssl/md5.h use b #link ssl # LDLIBS="-lssl -lcrypto" hash-link cstr version = "1.0" cstr description = "hash link - Sam Watkins, 2009" cstr usage[] = { "[-s|-S] out-dir in-dir ...", "--help", NULL } opts *O cstr options[][3] = { "V", "version", "" }, { "s", "sympath", "symlink hash files over original files" }, { "S", "symname", "symlink hash leafnames over original files" }, { NULL, NULL, NULL } Main() O = get_options(options) if opt("help") help() eif opt("version") version() else hash_link_main() enum {SYMLINK_NO, SYMLINK_PATH, SYMLINK_NAME} use_symlink = SYMLINK_NO hash_link_main() args(cstr, hash_dir) mkdir(hash_dir, 0777) if opt("sympath") use_symlink = SYMLINK_PATH if opt("symname") use_symlink = SYMLINK_NAME find_main(f, s) if S_ISREG(s->st_mode) uchar sha1sum[SHA_DIGEST_LENGTH] # char sha1sum_hex[SHA_DIGEST_LENGTH*2+1] uchar md5sum[MD5_DIGEST_LENGTH] # char md5sum_hex[MD5_DIGEST_LENGTH*2+1] char hash_file[SHA_DIGEST_LENGTH*2+1+MD5_DIGEST_LENGTH*2+1] size_t length = 0 new(sha1, SHA_CTX) new(md5, MD5_CTX) int fd = Open(f, O_RDONLY) each_block(b, fd) char *start = buffer_get_start(b) size_t size = buffer_get_size(b) SHA1_Update(sha1, start, size) MD5_Update(md5, start, size) length += size final(sha1, SHA_CTX, sha1sum) final(md5, MD5_CTX, md5sum) uchar *ch char *out = hash_file for ch=&sha1sum[0]; ch < sha1sum+SHA_DIGEST_LENGTH; ++ch, out+=2 snprintf(out, 3, "%02x", *ch) *(out++) = '-'; for ch=&md5sum[0]; ch < md5sum+MD5_DIGEST_LENGTH; ++ch, out+=2 snprintf(out, 3, "%02x", *ch) *out = '\0'; cstr hash_path = path_cat(hash_dir, hash_file) if exists(hash_path) Remove(f) else Rename(f, hash_path) if use_symlink == SYMLINK_NO Link(hash_path, f) if use_symlink == SYMLINK_PATH Symlink(hash_path, f) if use_symlink == SYMLINK_NAME Symlink(hash_file, f) Sayf("%s\t%s", hash_file, f) Close(fd) # LIBB def each_block(b, fd) new(b, buffer, block_size) repeat buffer_set_size(b, Read(fd, buffer_get_start(b), block_size)) if buffer_get_size(b) == 0 break . def SHA_CTX_init(sha1) SHA1_Init(sha1) def SHA_CTX_final(sha1, md) SHA1_Final(md, sha1) def MD5_CTX_init(md5) MD5_Init(md5) def MD5_CTX_final(md5, md) MD5_Final(md, md5) def final(o, type) type^^_final(o) def final(o, type, a0) type^^_final(o, a0) def final(o, type, a0, a1) type^^_final(o, a0, a1)