diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 505724bb..2e060564 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -102,7 +102,7 @@ int HIDDEN xbps_entry_install_conf_file(prop_dictionary_t, const char *); /** * @private - * From lib/plist.c + * From lib/plist_archive_entry.c * * Finds a proplib dictionary in an archive, matching a specific * entry on it. diff --git a/lib/Makefile b/lib/Makefile index f1b28555..29b3f24e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -43,7 +43,7 @@ OBJS += package_unpack.o package_requiredby.o package_register.o OBJS += package_purge.o package_replaces.o package_properties.o OBJS += transaction_dictionary.o transaction_sortdeps.o OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o -OBJS += util.o pkgmatch.o mkpath.o initend.o +OBJS += plist_archive_entry.o util.o pkgmatch.o mkpath.o initend.o OBJS += regpkgdb_dictionary.o repository_register.o OBJS += repository_findpkg.o repository_plist.o repository_finddeps.o OBJS += repository_pool.o repository_sync_index.o diff --git a/lib/plist.c b/lib/plist.c index 292d8a88..d3976450 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -29,7 +29,6 @@ #include #include -#include #include #include "xbps_api_impl.h" @@ -689,129 +688,3 @@ xbps_remove_pkg_dict_from_plist_by_name(const char *pkg, const char *plist) return true; } - -/* - * Takes a compressed data buffer, decompresses it and returns the - * new buffer uncompressed if all was right. - */ -#define _READ_CHUNK 512 - -static char * -_xbps_uncompress_plist_data(char *xml, size_t len) -{ - z_stream strm; - unsigned char out[_READ_CHUNK]; - char *uncomp_xml = NULL; - size_t have; - ssize_t totalsize = 0; - int rv = 0; - - assert(xml != NULL); - - /* Decompress the mmap'ed buffer with zlib */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - - /* 15+16 to use gzip method */ - if (inflateInit2(&strm, 15+16) != Z_OK) - return NULL; - - strm.avail_in = len; - strm.next_in = (unsigned char *)xml; - - /* Output buffer (uncompressed) */ - uncomp_xml = malloc(_READ_CHUNK); - if (uncomp_xml == NULL) { - (void)inflateEnd(&strm); - return NULL; - } - - /* Inflate the input buffer and copy into 'uncomp_xml' */ - do { - strm.avail_out = _READ_CHUNK; - strm.next_out = out; - rv = inflate(&strm, Z_NO_FLUSH); - switch (rv) { - case Z_DATA_ERROR: - /* - * Wrong compressed data or uncompressed, try - * normal method as last resort. - */ - (void)inflateEnd(&strm); - free(uncomp_xml); - errno = EAGAIN; - return NULL; - case Z_STREAM_ERROR: - case Z_NEED_DICT: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - free(uncomp_xml); - return NULL; - } - have = _READ_CHUNK - strm.avail_out; - totalsize += have; - uncomp_xml = realloc(uncomp_xml, totalsize); - memcpy(uncomp_xml + totalsize - have, out, have); - } while (strm.avail_out == 0); - - /* we are done */ - (void)inflateEnd(&strm); - - return uncomp_xml; -} -#undef _READ_CHUNK - -prop_dictionary_t HIDDEN -xbps_read_dict_from_archive_entry(struct archive *ar, - struct archive_entry *entry) -{ - prop_dictionary_t d = NULL; - size_t buflen = 0; - ssize_t nbytes = -1; - char *buf, *uncomp_buf; - - assert(ar != NULL); - assert(entry != NULL); - - buflen = (size_t)archive_entry_size(entry); - buf = malloc(buflen); - if (buf == NULL) - return NULL; - - nbytes = archive_read_data(ar, buf, buflen); - if ((size_t)nbytes != buflen) { - free(buf); - return NULL; - } - - uncomp_buf = _xbps_uncompress_plist_data(buf, buflen); - if (uncomp_buf == NULL) { - if (errno && errno != EAGAIN) { - /* Error while decompressing */ - free(buf); - return NULL; - } else if (errno == EAGAIN) { - /* Not a compressed data, try again */ - errno = 0; - d = prop_dictionary_internalize(buf); - free(buf); - } - } else { - /* We have the uncompressed data */ - d = prop_dictionary_internalize(uncomp_buf); - free(uncomp_buf); - free(buf); - } - - if (d == NULL) - return NULL; - else if (prop_object_type(d) != PROP_TYPE_DICTIONARY) { - prop_object_release(d); - return NULL; - } - - return d; -} diff --git a/lib/plist_archive_entry.c b/lib/plist_archive_entry.c new file mode 100644 index 00000000..34352bdc --- /dev/null +++ b/lib/plist_archive_entry.c @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2008-2011 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "xbps_api_impl.h" + +/* + * Takes a compressed data buffer, decompresses it and returns the + * new buffer uncompressed if all was right. + */ +#define _READ_CHUNK 512 + +static char * +_xbps_uncompress_plist_data(char *xml, size_t len) +{ + z_stream strm; + unsigned char out[_READ_CHUNK]; + char *uncomp_xml = NULL; + size_t have; + ssize_t totalsize = 0; + int rv = 0; + + assert(xml != NULL); + + /* Decompress the mmap'ed buffer with zlib */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + /* 15+16 to use gzip method */ + if (inflateInit2(&strm, 15+16) != Z_OK) + return NULL; + + strm.avail_in = len; + strm.next_in = (unsigned char *)xml; + + /* Output buffer (uncompressed) */ + uncomp_xml = malloc(_READ_CHUNK); + if (uncomp_xml == NULL) { + (void)inflateEnd(&strm); + return NULL; + } + + /* Inflate the input buffer and copy into 'uncomp_xml' */ + do { + strm.avail_out = _READ_CHUNK; + strm.next_out = out; + rv = inflate(&strm, Z_NO_FLUSH); + switch (rv) { + case Z_DATA_ERROR: + /* + * Wrong compressed data or uncompressed, try + * normal method as last resort. + */ + (void)inflateEnd(&strm); + free(uncomp_xml); + errno = EAGAIN; + return NULL; + case Z_STREAM_ERROR: + case Z_NEED_DICT: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + free(uncomp_xml); + return NULL; + } + have = _READ_CHUNK - strm.avail_out; + totalsize += have; + uncomp_xml = realloc(uncomp_xml, totalsize); + memcpy(uncomp_xml + totalsize - have, out, have); + } while (strm.avail_out == 0); + + /* we are done */ + (void)inflateEnd(&strm); + + return uncomp_xml; +} +#undef _READ_CHUNK + +prop_dictionary_t HIDDEN +xbps_read_dict_from_archive_entry(struct archive *ar, + struct archive_entry *entry) +{ + prop_dictionary_t d = NULL; + size_t buflen = 0; + ssize_t nbytes = -1; + char *buf, *uncomp_buf; + + assert(ar != NULL); + assert(entry != NULL); + + buflen = (size_t)archive_entry_size(entry); + buf = malloc(buflen); + if (buf == NULL) + return NULL; + + nbytes = archive_read_data(ar, buf, buflen); + if ((size_t)nbytes != buflen) { + free(buf); + return NULL; + } + + uncomp_buf = _xbps_uncompress_plist_data(buf, buflen); + if (uncomp_buf == NULL) { + if (errno && errno != EAGAIN) { + /* Error while decompressing */ + free(buf); + return NULL; + } else if (errno == EAGAIN) { + /* Not a compressed data, try again */ + errno = 0; + d = prop_dictionary_internalize(buf); + free(buf); + } + } else { + /* We have the uncompressed data */ + d = prop_dictionary_internalize(uncomp_buf); + free(uncomp_buf); + free(buf); + } + + if (d == NULL) + return NULL; + else if (prop_object_type(d) != PROP_TYPE_DICTIONARY) { + prop_object_release(d); + return NULL; + } + + return d; +}