diff --git a/util.h b/util.h
index dd12df7eaf94f0595b426325a84a414efd4998d7..d3b3861005f2df24a17b82c92978309b2ca20131 100644
--- a/util.h
+++ b/util.h
@@ -12,6 +12,7 @@ char *vmprintf(const char *fmt, va_list ap);
 char *mprintf(const char *fmt, ...);
 
 void *xmalloc(size_t size);
+char *hashfile(char *path);
 
 /* JSON av parsing */
 void parse_dict(AVDictionary **d, char *s);
diff --git a/util/hashfile.c b/util/hashfile.c
new file mode 100644
index 0000000000000000000000000000000000000000..e7dc5e8bc4b52b08b295fbdb26376836563daf39
--- /dev/null
+++ b/util/hashfile.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libavutil/md5.h>
+
+#include "../util.h"
+
+char *hashfile(char *path)
+{
+	struct AVMD5 *ctx;
+	int i, fd;
+	char *ptr, *buf;
+	size_t len, size;
+	FILE *stream;
+	if ((fd = open(path, O_RDONLY)) < 0)
+		job_failed("Could not open file for hashing: %s", strerror(errno));
+	if (!(ctx = av_md5_alloc()))
+		exit(99);
+	av_md5_init(ctx);
+	buf = xmalloc(4096);
+	while ((len = read(fd, buf, 4096)) > 0)
+		av_md5_update(ctx, buf, len);
+	if (len < 0)
+		job_failed("Could not read file for hashing: %s", strerror(errno));
+	close(fd);
+	av_md5_final(ctx, buf);
+	av_free(ctx);
+	if (!(stream = open_memstream(&ptr, &size)))
+		exit(99);
+	fprintf(stream, "md5:");
+	for (i = 0; i < 16; i ++)
+		fprintf(stream, "%02hhx", buf[i]);
+	free(buf);
+	fclose(stream);
+	return ptr;
+}