diff --git a/src/hash.rs b/src/hash.rs
index 36cbbf4520b044cd81ade70d92f1134bc8aa72cd..94a6db2ec91a96e31f983c3b3454bf22e8db32b6 100644
--- a/src/hash.rs
+++ b/src/hash.rs
@@ -1,4 +1,4 @@
-use libc::{c_char, c_int};
+use libc::{c_char, c_int, size_t};
 use std::ffi::CString;
 use std::os::unix::ffi::OsStrExt;
 use std::path::Path;
@@ -27,22 +27,30 @@ pub fn md5_file(path: &Path,
 
 #[link(name = "hash")]
 extern {
-    fn hash_md5_symlink(path: *const c_char,
-                     flags: c_int,
-                     hash: &mut [u8;16]) -> c_int;
+    fn hash_md5_buf(buf: *const c_char,
+                    length: size_t,
+                    flags: c_int,
+                    hash: &mut [u8;16]) -> c_int;
 }
 
 pub fn md5_symlink(path: &Path,
                    flags: c_int) -> Result<String>
 {
-    let mut hash: [u8;16] = [0;16];
-    let cstring = CString::new(path.as_os_str().as_bytes()).unwrap();
-    if unsafe { hash_md5_symlink(cstring.as_ptr(), flags, &mut hash) } < 0 {
-        Err(Error::last_os_error())
-    } else {
-        let s: Vec<String> = hash.iter().map(
-            |b| format!("{:02x}", b)).collect();
-        Ok(s.join(""))
+    match path.read_link() {
+        Ok(symlink) => {
+            let cstring = CString::new(symlink.as_os_str().as_bytes()).unwrap();
+            let length = cstring.to_bytes().len();
+            let ptr = cstring.as_ptr();
+            let mut hash: [u8;16] = [0;16];
+            if unsafe { hash_md5_buf(ptr, length, flags, &mut hash) } < 0 {
+                Err(Error::last_os_error())
+            } else {
+                let s: Vec<String> = hash.iter().map(
+                    |b| format!("{:02x}", b)).collect();
+                Ok(s.join(""))
+            }
+        },
+        Err(e) => Err(e)
     }
 }
 
@@ -69,22 +77,30 @@ pub fn sha512_file(path: &Path,
 
 #[link(name = "hash")]
 extern {
-    fn hash_sha512_symlink(path: *const c_char,
-                           flags: c_int,
-                           hash: &mut [u8;64]) -> c_int;
+    fn hash_sha512_buf(buf: *const c_char,
+                       length: size_t,
+                       flags: c_int,
+                       hash: &mut [u8;64]) -> c_int;
 }
 
 pub fn sha512_symlink(path: &Path,
-                      flags: c_int) -> Result<String>
+                   flags: c_int) -> Result<String>
 {
-    let mut hash: [u8;64] = [0;64];
-    let cstring = CString::new(path.as_os_str().as_bytes()).unwrap();
-    if unsafe { hash_sha512_symlink(cstring.as_ptr(), flags, &mut hash) } < 0 {
-        Err(Error::last_os_error())
-    } else {
-        let s: Vec<String> = hash.iter().map(
-            |b| format!("{:02x}", b)).collect();
-        Ok(s.join(""))
+    match path.read_link() {
+        Ok(symlink) => {
+            let cstring = CString::new(symlink.as_os_str().as_bytes()).unwrap();
+            let length = cstring.to_bytes().len();
+            let ptr = cstring.as_ptr();
+            let mut hash: [u8;64] = [0;64];
+            if unsafe { hash_sha512_buf(ptr, length, flags, &mut hash) } < 0 {
+                Err(Error::last_os_error())
+            } else {
+                let s: Vec<String> = hash.iter().map(
+                    |b| format!("{:02x}", b)).collect();
+                Ok(s.join(""))
+            }
+        },
+        Err(e) => Err(e)
     }
 }
 
diff --git a/src/md5sum.c b/src/md5sum.c
index b827c3052f0be8c55359ff864a9398ab338894e8..1a85d6a88362245847da2cdd17ca266a376b4b2d 100644
--- a/src/md5sum.c
+++ b/src/md5sum.c
@@ -11,26 +11,18 @@
 
 #define BLOCKSIZE 4096
 
-int hash_md5_symlink(char *filename,
-                     int flags,
-                     unsigned char *hash)
+int hash_md5_buf(char *buf,
+                 size_t length,
+                 int flags,
+                 unsigned char *hash)
 {
-  char buf[PATH_MAX];
-  int n;
   
-  n = readlink(filename, buf, sizeof(buf));
-  if (n < 0) {
-    return -1;
-  } else if (n == PATH_MAX) {
-    errno = ENAMETOOLONG;
-    return -1;
-  } else {
-    MD5_CTX ctx;
+  MD5_CTX ctx;
+  
+  MD5_Init(&ctx);
+  MD5_Update(&ctx, buf, length);
+  MD5_Final(hash, &ctx);
 
-    MD5_Init(&ctx);
-    MD5_Update(&ctx, buf, n);
-    MD5_Final(hash, &ctx);
-  }
   return 0;
 }
 
diff --git a/src/sha512sum.c b/src/sha512sum.c
index 34d9674069f258339566f2556e3969ac42407164..0ddb35552a6e7f084bc1846758d4f1feea12af9e 100644
--- a/src/sha512sum.c
+++ b/src/sha512sum.c
@@ -11,26 +11,17 @@
 
 #define BLOCKSIZE 4096
 
-int hash_sha512_symlink(char *filename,
-                        int flags,
-                        unsigned char *hash)
+int hash_sha512_buf(char *buf,
+                    size_t length,
+                    int flags,
+                    unsigned char *hash)
 {
-  char buf[PATH_MAX];
-  int n;
+  SHA512_CTX ctx;
   
-  n = readlink(filename, buf, sizeof(buf));
-  if (n < 0) {
-    return -1;
-  } else if (n == PATH_MAX) {
-    errno = ENAMETOOLONG;
-    return -1;
-  } else {
-    SHA512_CTX ctx;
+  SHA512_Init(&ctx);
+  SHA512_Update(&ctx, buf, length);
+  SHA512_Final(hash, &ctx);
 
-    SHA512_Init(&ctx);
-    SHA512_Update(&ctx, buf, n);
-    SHA512_Final(hash, &ctx);
-  }
   return 0;
 }