Add zip_source_zip_create().
diff --git a/TODO.md b/TODO.md
index 246a05c..76c2449 100644
--- a/TODO.md
+++ b/TODO.md
@@ -123,7 +123,7 @@
   * support testing on macOS
 * add test cases for lots of files (including too many)
 * add test cases for holes (between files, between files and cdir, between cdir and eocd, + zip64 where appropriate)
-* test seek in `zip_source_crc()`
+* test seek in `zip_source_crc_create()`
 * test cases for `set_extra*`, `delete_extra*`, `*extra_field*`
 * test cases for in memory archives
   * add
diff --git a/developer-xcode/libzip.xcodeproj/project.pbxproj b/developer-xcode/libzip.xcodeproj/project.pbxproj
index 02262ff..0528012 100644
--- a/developer-xcode/libzip.xcodeproj/project.pbxproj
+++ b/developer-xcode/libzip.xcodeproj/project.pbxproj
@@ -904,7 +904,7 @@
 		4BDC722715B1B25E00236D3C /* zip_set_name.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_set_name.c; path = ../lib/zip_set_name.c; sourceTree = "<group>"; };
 		4BDC722815B1B25E00236D3C /* zip_source_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_buffer.c; path = ../lib/zip_source_buffer.c; sourceTree = "<group>"; };
 		4BDC722915B1B25E00236D3C /* zip_source_close.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_close.c; path = ../lib/zip_source_close.c; sourceTree = "<group>"; };
-		4BDC722A15B1B25E00236D3C /* zip_source_crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_crc.c; path = ../lib/zip_source_crc.c; sourceTree = "<group>"; };
+		4BDC722A15B1B25E00236D3C /* zip_source_crc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_crc.c; sourceTree = "<group>"; };
 		4BDC722C15B1B25E00236D3C /* zip_source_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_error.c; path = ../lib/zip_source_error.c; sourceTree = "<group>"; };
 		4BDC722F15B1B25E00236D3C /* zip_source_free.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_free.c; path = ../lib/zip_source_free.c; sourceTree = "<group>"; };
 		4BDC723015B1B25E00236D3C /* zip_source_function.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_function.c; path = ../lib/zip_source_function.c; sourceTree = "<group>"; };
@@ -912,7 +912,7 @@
 		4BDC723215B1B25E00236D3C /* zip_source_open.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_open.c; path = ../lib/zip_source_open.c; sourceTree = "<group>"; };
 		4BDC723515B1B25E00236D3C /* zip_source_read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_read.c; path = ../lib/zip_source_read.c; sourceTree = "<group>"; };
 		4BDC723615B1B25E00236D3C /* zip_source_stat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_stat.c; path = ../lib/zip_source_stat.c; sourceTree = "<group>"; };
-		4BDC723715B1B25E00236D3C /* zip_source_window.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_window.c; path = ../lib/zip_source_window.c; sourceTree = "<group>"; };
+		4BDC723715B1B25E00236D3C /* zip_source_window.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip_source_window.c; sourceTree = "<group>"; };
 		4BDC723815B1B25E00236D3C /* zip_source_zip_new.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_zip_new.c; path = ../lib/zip_source_zip_new.c; sourceTree = "<group>"; };
 		4BDC723915B1B25E00236D3C /* zip_source_zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_source_zip.c; path = ../lib/zip_source_zip.c; sourceTree = "<group>"; };
 		4BDC723A15B1B25E00236D3C /* zip_stat_index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = zip_stat_index.c; path = ../lib/zip_stat_index.c; sourceTree = "<group>"; };
diff --git a/lib/zip.h b/lib/zip.h
index 3b779f0..47568d9 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -465,6 +465,7 @@
 #endif
 ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
 ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
+ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
 ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
 ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
 ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull);
diff --git a/lib/zip_close.c b/lib/zip_close.c
index f10110a..1bc7c78 100644
--- a/lib/zip_close.c
+++ b/lib/zip_close.c
@@ -207,7 +207,7 @@
 
             zs = NULL;
             if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
-                if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
+                if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) {
                     error = 1;
                     break;
                 }
@@ -412,7 +412,7 @@
     }
 
     if (needs_crc) {
-        if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
+        if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
             zip_source_free(src_final);
             return -1;
         }
diff --git a/lib/zip_fopen_index_encrypted.c b/lib/zip_fopen_index_encrypted.c
index 280a5bd..8c8a80d 100644
--- a/lib/zip_fopen_index_encrypted.c
+++ b/lib/zip_fopen_index_encrypted.c
@@ -49,7 +49,7 @@
         password = NULL;
     }
     
-    if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
+    if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL)
         return NULL;
 
     if (zip_source_open(src) < 0) {
diff --git a/lib/zip_source_crc.c b/lib/zip_source_crc.c
index ab38b13..7d01f04 100644
--- a/lib/zip_source_crc.c
+++ b/lib/zip_source_crc.c
@@ -52,16 +52,16 @@
 
 
 zip_source_t *
-zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
+zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
     struct crc_context *ctx;
 
     if (src == NULL) {
-        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(error, ZIP_ER_INVAL, 0);
         return NULL;
     }
 
     if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
-        zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+        zip_error_set(error, ZIP_ER_MEMORY, 0);
         return NULL;
     }
 
@@ -72,7 +72,7 @@
     ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
     ctx->size = 0;
 
-    return zip_source_layered(za, src, crc_read, ctx);
+    return zip_source_layered_create(src, crc_read, ctx, error);
 }
 
 
diff --git a/lib/zip_source_window.c b/lib/zip_source_window.c
index 89344e1..a8ebc25 100644
--- a/lib/zip_source_window.c
+++ b/lib/zip_source_window.c
@@ -58,8 +58,8 @@
 
 
 zip_source_t *
-zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) {
-    return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error);
+zip_source_window_create(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, zip_error_t *error) {
+    return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, error);
 }
 
 
diff --git a/lib/zip_source_zip.c b/lib/zip_source_zip.c
index cb62540..985dac8 100644
--- a/lib/zip_source_zip.c
+++ b/lib/zip_source_zip.c
@@ -36,21 +36,24 @@
 
 #include "zipint.h"
 
-
-ZIP_EXTERN zip_source_t *
-zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) {
+ZIP_EXTERN zip_source_t *zip_source_zip_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, zip_error_t *error) {
     if (len < -1) {
-        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(error, ZIP_ER_INVAL, 0);
         return NULL;
     }
-
+    
     if (len == -1)
         len = 0;
-
+    
     if (start == 0 && len == 0)
         flags |= ZIP_FL_COMPRESSED;
     else
         flags &= ~ZIP_FL_COMPRESSED;
+    
+    return _zip_source_zip_new(srcza, srcidx, flags, start, (zip_uint64_t)len, NULL, error);
+}
 
-    return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL);
+
+ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) {
+    return zip_source_zip_create(srcza, srcidx, flags, start, len, &za->error);
 }
diff --git a/lib/zip_source_zip_new.c b/lib/zip_source_zip_new.c
index ffb2bdf..b105c73 100644
--- a/lib/zip_source_zip_new.c
+++ b/lib/zip_source_zip_new.c
@@ -38,30 +38,25 @@
 
 static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de);
 
-zip_source_t *
-_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) {
+zip_source_t *_zip_source_zip_new(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password, zip_error_t *error) {
     zip_source_t *src, *s2;
     zip_stat_t st;
     zip_file_attributes_t attributes;
     zip_dirent_t *de;
     bool partial_data, needs_crc, needs_decrypt, needs_decompress;
 
-    if (za == NULL) {
-        return NULL;
-    }
-
     if (srcza == NULL || srcidx >= srcza->nentry) {
-        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(error, ZIP_ER_INVAL, 0);
         return NULL;
     }
 
     if ((flags & ZIP_FL_UNCHANGED) == 0 && (ZIP_ENTRY_DATA_CHANGED(srcza->entry + srcidx) || srcza->entry[srcidx].deleted)) {
-        zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+        zip_error_set(error, ZIP_ER_CHANGED, 0);
         return NULL;
     }
 
     if (zip_stat_index(srcza, srcidx, flags | ZIP_FL_UNCHANGED, &st) < 0) {
-        zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+        zip_error_set(error, ZIP_ER_INTERNAL, 0);
         return NULL;
     }
 
@@ -70,13 +65,13 @@
     }
 
     if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) {
-        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(error, ZIP_ER_INVAL, 0);
         return NULL;
     }
 
     /* overflow or past end of file */
     if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) {
-        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+        zip_error_set(error, ZIP_ER_INVAL, 0);
         return NULL;
     }
 
@@ -92,21 +87,21 @@
 
     if (needs_decrypt) {
         if (password == NULL) {
-            password = za->default_password;
+            password = srcza->default_password;
         }
         if (password == NULL) {
-            zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
+            zip_error_set(error, ZIP_ER_NOPASSWD, 0);
             return NULL;
         }
     }
 
-    if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
+    if ((de = _zip_get_dirent(srcza, srcidx, flags, error)) == NULL) {
         return NULL;
     }
     _zip_file_attributes_from_dirent(&attributes, de);
 
     if (st.comp_size == 0) {
-        return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes);
+        return zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error);
     }
 
     if (partial_data && !needs_decrypt && !needs_decompress) {
@@ -118,12 +113,12 @@
         st2.mtime = st.mtime;
         st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
 
-        if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) {
+        if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, error)) == NULL) {
             return NULL;
         }
     }
     else {
-        if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) {
+        if ((src =  _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, error)) == NULL) {
             return NULL;
         }
     }
@@ -139,11 +134,11 @@
         zip_encryption_implementation enc_impl;
 
         if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
-            zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
+            zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
             return NULL;
         }
 
-        s2 = enc_impl(za, src, st.encryption_method, 0, password);
+        s2 = enc_impl(srcza, src, st.encryption_method, 0, password);
         zip_source_free(src);
         if (s2 == NULL) {
             return NULL;
@@ -151,7 +146,7 @@
         src = s2;
     }
     if (needs_decompress) {
-        s2 = zip_source_decompress(za, src, st.comp_method);
+        s2 = zip_source_decompress(srcza, src, st.comp_method);
         zip_source_free(src);
         if (s2 == NULL) {
             return NULL;
@@ -159,7 +154,7 @@
         src = s2;
     }
     if (needs_crc) {
-        s2 = zip_source_crc(za, src, 1);
+        s2 = zip_source_crc_create(src, 1, error);
         zip_source_free(src);
         if (s2 == NULL) {
             return NULL;
@@ -168,7 +163,7 @@
     }
 
     if (partial_data && (needs_decrypt || needs_decompress)) {
-        s2 = zip_source_window(za, src, start, len);
+        s2 = zip_source_window_create(src, start, len, error);
         zip_source_free(src);
         if (s2 == NULL) {
             return NULL;
diff --git a/lib/zipint.h b/lib/zipint.h
index 5d72508..e86c2e9 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -172,7 +172,7 @@
 
 typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd);
 zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags);
-zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
+zip_source_t *zip_source_crc_create(zip_source_t *, int, zip_error_t *error);
 zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm);
 zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
 zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
@@ -180,10 +180,11 @@
 zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 int zip_source_remove(zip_source_t *);
 zip_int64_t zip_source_supports(zip_source_t *src);
-zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
+zip_source_t *zip_source_window_create(zip_source_t *, zip_uint64_t, zip_uint64_t, zip_error_t *error);
 zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
 zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes);
+zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
 
 /* error source for layered sources */
 
@@ -608,7 +609,7 @@
 zip_source_t *_zip_source_new(zip_error_t *error);
 int _zip_source_set_source_archive(zip_source_t *, zip_t *);
 zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
-zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
+zip_source_t *_zip_source_zip_new(zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *, zip_error_t *error);
 
 int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);
 int _zip_string_equal(const zip_string_t *, const zip_string_t *);
diff --git a/man/zip_source_zip.mdoc b/man/zip_source_zip.mdoc
index 974842e..0b79134 100644
--- a/man/zip_source_zip.mdoc
+++ b/man/zip_source_zip.mdoc
@@ -29,11 +29,12 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd December 18, 2017
+.Dd April 4, 2021
 .Dt ZIP_SOURCE_ZIP 3
 .Os
 .Sh NAME
-.Nm zip_source_zip
+.Nm zip_source_zip ,
+.Nm zip_source_zip_create
 .Nd create data source from zip file
 .Sh LIBRARY
 libzip (-lzip)
@@ -41,10 +42,14 @@
 .In zip.h
 .Ft zip_source_t *
 .Fn zip_source_zip "zip_t *archive" "zip_t *srcarchive" "zip_uint64_t srcidx" "zip_flags_t flags" "zip_uint64_t start" "zip_int64_t len"
+.Ft zip_source_t *
+.Fn zip_source_zip_create "zip_t *srcarchive" "zip_uint64_t srcidx" "zip_flags_t flags" "zip_uint64_t start" "zip_int64_t len" "zip_error_t *error"
 .Sh DESCRIPTION
-The function
+The functions
 .Fn zip_source_zip
-creates a zip source from a file in a zip archive.
+and
+.Fn zip_source_zip_create
+create a zip source from a file in a zip archive.
 The
 .Ar srcarchive
 argument is the (open) zip archive containing the source zip file
@@ -84,10 +89,14 @@
 .Dv NULL
 is returned and the error code in
 .Ar archive
+or
+.Ar error
 is set to indicate the error.
 .Sh ERRORS
 .Fn zip_source_zip
-fails if:
+and
+.Fn zip_source_zip_create
+fail if:
 .Bl -tag -width Er
 .It Bq Er ZIP_ER_CHANGED
 Unchanged data was requested, but it is not available.
@@ -113,6 +122,8 @@
 .Sh HISTORY
 .Fn zip_source_zip
 was added in libzip 1.0.
+.Fn zip_source_zip_create
+was added in libzip 1.8.0.
 .Sh AUTHORS
 .An -nosplit
 .An Dieter Baron Aq Mt dillo@nih.at