Implement I/O abstraction layer. Finally.
diff --git a/lib/zip_source_read.c b/lib/zip_source_read.c
index 910649d..8249b82 100644
--- a/lib/zip_source_read.c
+++ b/lib/zip_source_read.c
@@ -1,6 +1,6 @@
 /*
   zip_source_read.c -- read data from zip_source
-  Copyright (C) 2009 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,25 +38,13 @@
 zip_int64_t
 zip_source_read(struct zip_source *src, void *data, zip_uint64_t len)
 {
-    zip_int64_t ret;
-
-    if (!src->is_open || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) {
-	src->error_source = ZIP_LES_INVAL;
+    if (src->source_closed) {
+        return -1;
+    }
+    if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) {
+        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
 	return -1;
     }
 
-    if (src->src == NULL)
-	return src->cb.f(src->ud, data, len, ZIP_SOURCE_READ);
-
-    ret = src->cb.l(src->src, src->ud, data, len, ZIP_SOURCE_READ);
-
-    if (ret < 0) {
-	if (ret == ZIP_SOURCE_ERR_LOWER)
-	    src->error_source = ZIP_LES_LOWER;
-	else
-	    src->error_source = ZIP_LES_UPPER;
-	return -1;
-    }
-    
-    return ret;
+    return _zip_source_call(src, data, len, ZIP_SOURCE_READ);
 }