diff --git a/bin/Makefile b/bin/Makefile index f7f50693..3d578483 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -1,9 +1,9 @@ -include ../config.mk -SUBDIRS = xbps-uhelper +SUBDIRS = xbps-bin SUBDIRS += xbps-repo -SUBDIRS += xbps-bin SUBDIRS += xbps-dgraph +SUBDIRS += xbps-uhelper .PHONY: all all: diff --git a/bin/xbps-bin/Makefile b/bin/xbps-bin/Makefile index 3a72fbf5..3a34d986 100644 --- a/bin/xbps-bin/Makefile +++ b/bin/xbps-bin/Makefile @@ -3,8 +3,8 @@ TOPDIR = ../.. BIN = xbps-bin OBJS = check.o install.o main.o remove.o show-deps.o -OBJS += show-info-files.o ../xbps-repo/util.o find-files.o -OBJS += question.o +OBJS += show-info-files.o util.o find-files.o +OBJS += question.o fetch.o MAN = $(BIN).8 include $(TOPDIR)/prog.mk diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index d65f6edc..42ca750f 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -30,6 +30,8 @@ #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #endif +#include + int xbps_install_new_pkg(const char *); int xbps_update_pkg(const char *); int xbps_autoupdate_pkgs(bool); @@ -43,7 +45,22 @@ int xbps_show_pkg_reverse_deps(const char *); int show_pkg_info_from_metadir(const char *); int show_pkg_files_from_metadir(const char *); int find_files_in_packages(const char *); + +/* from question.c */ bool xbps_yesno(const char *, ...); bool xbps_noyes(const char *, ...); +/* from fetch.c */ +void fetch_file_progress_cb(void *); + +/* From util.c */ +int show_pkg_files(prop_dictionary_t); +void show_pkg_info(prop_dictionary_t); +void show_pkg_info_only_repo(prop_dictionary_t); +int show_pkg_namedesc(prop_object_t, void *, bool *); +int list_strings_in_array(prop_object_t, void *, bool *); +int list_strings_sep_in_array(prop_object_t, void *, bool *); +size_t find_longest_pkgver(prop_dictionary_t); +void print_package_line(const char *); + #endif /* !_XBPS_BIN_DEFS_H_ */ diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index 5ffb3672..8018ef4c 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -100,6 +100,7 @@ static int download_package_list(prop_object_iterator_t iter) { prop_object_t obj; + struct xbps_fetch_progress_data xfpd; const char *pkgver, *repoloc, *filename, *cachedir, *sha256; char *binfile; int rv = 0; @@ -145,7 +146,8 @@ again: return errno; } printf("Downloading %s binary package ...\n", pkgver); - rv = xbps_fetch_file(binfile, cachedir, false, NULL); + rv = xbps_fetch_file(binfile, cachedir, false, NULL, + fetch_file_progress_cb, &xfpd); if (rv == -1) { fprintf(stderr, "xbps-bin: couldn't download `%s'\n", filename); @@ -426,7 +428,7 @@ replace_packages(prop_dictionary_t trans_dict, prop_dictionary_t pkgd, static void unpack_progress_cb_verbose(void *data) { - struct xbps_progress_data *xpd = data; + struct xbps_unpack_progress_data *xpd = data; if (xpd->entry == NULL || xpd->entry_is_metadata) return; @@ -441,18 +443,19 @@ unpack_progress_cb_verbose(void *data) static void unpack_progress_cb_percentage(void *data) { - struct xbps_progress_data *xpd = data; - int percent = 0; + struct xbps_unpack_progress_data *xpd = data; + double percent = 0; if (xpd->entry_is_metadata) return; percent = - (int)((xpd->entry_extract_count * 100) / xpd->entry_total_count); - if (percent > 100) - percent = 100; + (double)((xpd->entry_extract_count * 100.0) / xpd->entry_total_count); + if (percent > 100.0 || + xpd->entry_extract_count >= xpd->entry_total_count) + percent = 100.0; - printf("\033[s(%3d%%)\033[u", percent); + printf("\033[s(%3.2f%%)\033[u", percent); } static int @@ -461,7 +464,7 @@ exec_transaction(struct transaction *trans) prop_dictionary_t instpkgd; prop_object_t obj; prop_object_iterator_t replaces_iter; - struct xbps_progress_data xpd; + struct xbps_unpack_progress_data xpd; const char *pkgname, *version, *pkgver, *instver, *filen, *tract; int flags = xbps_get_flags(), rv = 0; bool update, preserve, autoinst; @@ -574,14 +577,14 @@ exec_transaction(struct transaction *trans) printf("Unpacking `%s' (from ../%s) ... ", pkgver, filen); if (flags & XBPS_FLAG_VERBOSE) { - xbps_unpack_binary_pkg_set_progress_cb( + rv = xbps_unpack_binary_pkg(obj, unpack_progress_cb_verbose, &xpd); printf("\n"); } else { - xbps_unpack_binary_pkg_set_progress_cb( + rv = xbps_unpack_binary_pkg(obj, unpack_progress_cb_percentage, &xpd); } - if ((rv = xbps_unpack_binary_pkg(obj)) != 0) { + if (rv != 0) { fprintf(stderr, "xbps-bin: error unpacking %s " "(%s)\n", pkgver, strerror(rv)); return rv; diff --git a/bin/xbps-bin/remove.c b/bin/xbps-bin/remove.c index 555dab67..8e6330c0 100644 --- a/bin/xbps-bin/remove.c +++ b/bin/xbps-bin/remove.c @@ -41,7 +41,7 @@ pkg_remove_and_purge(const char *pkgname, const char *version, bool purge) printf("Removing package %s-%s ...\n", pkgname, version); if ((rv = xbps_remove_pkg(pkgname, version, false)) != 0) { - fprintf(stderr, "\nE: unable to remove %s-%s (%s).\n", + xbps_error_printf("unable to remove %s-%s (%s).\n", pkgname, version, strerror(errno)); return rv; } @@ -49,7 +49,7 @@ pkg_remove_and_purge(const char *pkgname, const char *version, bool purge) printf(" Purging ... "); (void)fflush(stdout); if ((rv = xbps_purge_pkg(pkgname, false)) != 0) { - fprintf(stderr, "\nE: unable to purge %s-%s " + xbps_error_printf("unable to purge %s-%s " "(%s).\n", pkgname, version, strerror(errno)); return rv; @@ -149,7 +149,7 @@ xbps_remove_installed_pkgs(int argc, char **argv, bool yes, bool purge, found = true; reqby = prop_dictionary_get(dict, "requiredby"); if (reqby != NULL && prop_array_count(reqby) > 0) { - printf("WARNING: %s IS REQUIRED BY %u PACKAGES!\n", + xbps_warn_printf("%s IS REQUIRED BY %u PACKAGES!\n", pkgver, prop_array_count(reqby)); reqby_force = true; } @@ -184,7 +184,7 @@ xbps_remove_installed_pkgs(int argc, char **argv, bool yes, bool purge, prop_object_release(sorted_pkgs); return 0; } else if (reqby_force && force_rm_with_deps) - printf("WARNING: Forcing removal! you've been alerted.\n"); + xbps_warn_printf("Forcing removal! you've been alerted.\n"); for (x = 0; x < prop_array_count(sorted_pkgs); x++) { dict = prop_array_get(sorted_pkgs, x); diff --git a/bin/xbps-repo/util.c b/bin/xbps-bin/util.c similarity index 99% rename from bin/xbps-repo/util.c rename to bin/xbps-bin/util.c index e9c9603b..b6a19e28 100644 --- a/bin/xbps-repo/util.c +++ b/bin/xbps-bin/util.c @@ -34,6 +34,7 @@ #include #include "strlcpy.h" #include "defs.h" +#include "../xbps-repo/defs.h" void show_pkg_info_only_repo(prop_dictionary_t dict) diff --git a/bin/xbps-repo/Makefile b/bin/xbps-repo/Makefile index 59fdb3f6..c0716a27 100644 --- a/bin/xbps-repo/Makefile +++ b/bin/xbps-repo/Makefile @@ -2,7 +2,8 @@ TOPDIR = ../.. -include $(TOPDIR)/config.mk BIN = xbps-repo -OBJS = main.o util.o index.o repository.o find-files.o +OBJS = main.o index.o repository.o find-files.o +OBJS += ../xbps-bin/fetch.o ../xbps-bin/util.o MAN = $(BIN).8 include $(TOPDIR)/prog.mk diff --git a/bin/xbps-repo/defs.h b/bin/xbps-repo/defs.h index 1d67005c..38e2fdb1 100644 --- a/bin/xbps-repo/defs.h +++ b/bin/xbps-repo/defs.h @@ -38,15 +38,6 @@ int unregister_repository(const char *); int show_pkg_info_from_repolist(const char *); int show_pkg_deps_from_repolist(const char *); int repository_sync(void); -/* From util.c */ -int show_pkg_files(prop_dictionary_t); -void show_pkg_info(prop_dictionary_t); -void show_pkg_info_only_repo(prop_dictionary_t); -int show_pkg_namedesc(prop_object_t, void *, bool *); -int list_strings_in_array(prop_object_t, void *, bool *); -int list_strings_sep_in_array(prop_object_t, void *, bool *); -size_t find_longest_pkgver(prop_dictionary_t); -void print_package_line(const char *); /* From find-files.c */ int repo_find_files_in_packages(const char *); diff --git a/bin/xbps-repo/main.c b/bin/xbps-repo/main.c index 6c8633b1..a74b36bf 100644 --- a/bin/xbps-repo/main.c +++ b/bin/xbps-repo/main.c @@ -34,6 +34,7 @@ #include #include "defs.h" +#include "../xbps-bin/defs.h" static void __attribute__((noreturn)) usage(void) diff --git a/bin/xbps-repo/repository.c b/bin/xbps-repo/repository.c index 8cba9ecc..582a24bf 100644 --- a/bin/xbps-repo/repository.c +++ b/bin/xbps-repo/repository.c @@ -165,6 +165,7 @@ int register_repository(const char *uri) { struct repoinfo *rpi = NULL; + struct xbps_fetch_progress_data xfpd; const char *idxstr = NULL; char *metadir, *plist; int rv = 0; @@ -174,7 +175,8 @@ register_repository(const char *uri) if (xbps_check_is_repo_string_remote(idxstr)) { printf("Fetching remote package index at %s...\n", idxstr); - rv = xbps_repository_sync_pkg_index(idxstr); + rv = xbps_repository_sync_pkg_index(idxstr, + fetch_file_progress_cb, &xfpd); if (rv == -1) { fprintf(stderr, "E: could not fetch pkg index file: %s.\n", @@ -296,6 +298,7 @@ show_pkg_deps_from_repolist(const char *pkgname) static int repo_sync_pkg_index_cb(struct repository_pool_index *rpi, void *arg, bool *done) { + struct xbps_fetch_progress_data xfpd; struct repoinfo *rp; char *plist; int rv = 0; @@ -307,7 +310,8 @@ repo_sync_pkg_index_cb(struct repository_pool_index *rpi, void *arg, bool *done) return 0; printf("Syncing package index from: %s\n", rpi->rpi_uri); - rv = xbps_repository_sync_pkg_index(rpi->rpi_uri); + rv = xbps_repository_sync_pkg_index(rpi->rpi_uri, + fetch_file_progress_cb, &xfpd); if (rv == -1) { fprintf(stderr, "E: returned: %s\n", xbps_fetch_error_string()); return rv; diff --git a/bin/xbps-uhelper/Makefile b/bin/xbps-uhelper/Makefile index 64c06d33..f338e9ba 100644 --- a/bin/xbps-uhelper/Makefile +++ b/bin/xbps-uhelper/Makefile @@ -2,5 +2,6 @@ TOPDIR = ../.. -include $(TOPDIR)/config.mk BIN = xbps-uhelper +OBJS = main.o ../xbps-bin/fetch.o include $(TOPDIR)/prog.mk diff --git a/bin/xbps-uhelper/main.c b/bin/xbps-uhelper/main.c index 771040e0..1d1ebcbb 100644 --- a/bin/xbps-uhelper/main.c +++ b/bin/xbps-uhelper/main.c @@ -33,6 +33,7 @@ #include #include +#include "../xbps-bin/defs.h" /* error messages in bold/red */ #define MSG_ERROR "\033[1m\033[31m" @@ -103,6 +104,7 @@ usage(void) int main(int argc, char **argv) { + struct xbps_fetch_progress_data xfpd; prop_dictionary_t dict; const char *version; char *plist, *pkgname, *pkgver, *in_chroot_env, *hash; @@ -321,7 +323,8 @@ main(int argc, char **argv) usage(); for (i = 1; i < argc; i++) { - rv = xbps_fetch_file(argv[i], ".", false, "v"); + rv = xbps_fetch_file(argv[i], ".", false, "v", + fetch_file_progress_cb, &xfpd); if (rv == -1) { printf("%s: %s\n", argv[1], xbps_fetch_error_string()); diff --git a/include/xbps_api.h b/include/xbps_api.h index 221f6bf5..cc344605 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -119,9 +119,11 @@ __BEGIN_DECLS +void xbps_printf(const char *, ...); void xbps_dbg_printf(const char *, ...); void xbps_dbg_printf_append(const char *, ...); void xbps_error_printf(const char *, ...); +void xbps_warn_printf(const char *, ...); /** @addtogroup initend */ /*@{*/ @@ -194,6 +196,60 @@ int xbps_cmpver(const char *pkg1, const char *pkg2); /** @addtogroup download */ /*@{*/ +struct xbps_fetch_progress_data { + /* + * @var[out] file_size + * + * Filename size for the file to be fetched (set internally). + */ + off_t file_size; + /* + * @var[out] file_offset + * + * Current offset for the filename being fetched (set internally). + */ + off_t file_offset; + /* + * @var[out] file_dloaded; + * + * Bytes downloaded for the file being fetched (set internally). + */ + off_t file_dloaded; + /* + * @var[out] file_name; + * + * File name being fetched (set internally). + */ + const char *file_name; + /* + * @var[out] cb_start + * + * If true the function callback should be prepared to start + * the transfer progress (set internally). + */ + bool cb_start; + /* + * var[out] cb_update + * + * If true the function callback should be prepared to + * update the transfer progress (set internally). + */ + bool cb_update; + /* + * var[out] cb_end + * + * If true the function callback should be prepated to + * end the transfer progress (set internally). + */ + bool cb_end; + /* + * @var[in] cookie + * + * Pointer to private user data. + */ + void *cookie; +}; + /** * Download a file from a remote URL. * @@ -202,6 +258,10 @@ int xbps_cmpver(const char *pkg1, const char *pkg2); * @param[in] refetch If true and local/remote size/mtime do not match, * fetch the file from scratch. * @param[in] flags Flags passed to libfetch's fetchXget(). + * @param[in] progress_cb Pointer to a function callback to update the + * the fetch progress. + * @param[in] xfpd Pointer to a xbps_fetch_progress_data struct to be + * passed to the \a progress_cb callback as its argument. * * @return -1 on error, 0 if not downloaded (because local/remote size/mtime * do not match) and 1 if downloaded successfully. @@ -209,7 +269,9 @@ int xbps_cmpver(const char *pkg1, const char *pkg2); int xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, - const char *flags); + const char *flags, + void (*progress_cb)(void *), + struct xbps_fetch_progress_data *xfpd); /** * Returns last error string reported by xbps_fetch_file(). @@ -777,12 +839,18 @@ prop_dictionary_t * by the \a uri argument (if necessary). * * @param[in] uri URI to a remote repository. + * @param[in] progress_cb Pointer to a function callback to update the + * the fetch progress. + * @param[in] xfpd Pointer to a xbps_fetch_progress_data struct to be + * passed to the \a progress_cb callback as its argument. * * @return -1 on error (errno is set appropiately), 0 if transfer was * not necessary (local/remote size/mtime matched) or 1 if * downloaded successfully. */ -int xbps_repository_sync_pkg_index(const char *uri); +int xbps_repository_sync_pkg_index(const char *uri, + void (*progress_cb)(void *), + struct xbps_fetch_progress_data *xfpd); /*@}*/ @@ -863,10 +931,10 @@ int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state); /** @addtogroup unpack */ /** - * @struct xbps_progress_kdata xbps_api.h "xbps_api.h" + * @struct xbps_unpack_progress_data xbps_api.h "xbps_api.h" * @brief Structure to be passed to the unpacking progress function callback. */ -struct xbps_progress_data { +struct xbps_unpack_progress_data { /* * @var entry * @@ -910,25 +978,16 @@ struct xbps_progress_data { * * @param[in] trans_pkg_dict Package proplib dictionary as stored in the * \a packages array returned by the transaction dictionary. - * @param[in] Pointer to a function callback to update progress data + * @param[in] unpack_progress_cb Pointer to a function callback to update progress data * while extracting files in package (optional). - * @param[in] Pointer to a struct xbps_progress_data to be passed to + * @param[in] xupd Pointer to a struct xbps_unpack_progress_data to be passed to * the function callback \a unpack_progress_cb. * * @return 0 on success, otherwise an errno value. */ -int xbps_unpack_binary_pkg(prop_dictionary_t trans_pkg_dict); - -/** - * Sets a pointer to a function callback to update the unpack - * progress while \a xbps_unpack_binary_pkg is running. - * - * @param[in] fn Pointer to the function callback. - * @param[in] xpd Pointer to a "xbps_progress_data" structure - * to be passed as argument to the function callback. - */ -void xbps_unpack_binary_pkg_set_progress_cb(void (*fn)(void *), - struct xbps_progress_data *xpd); +int xbps_unpack_binary_pkg(prop_dictionary_t trans_pkg_dict, + void (*unpack_progress_cb)(void *), + struct xbps_unpack_progress_data *xupd); /*@}*/ diff --git a/lib/download.c b/lib/download.c index 57312fe0..21496dd9 100644 --- a/lib/download.c +++ b/lib/download.c @@ -51,142 +51,6 @@ * * These functions allow you to download files. */ -struct xferstat { - struct timeval start; - struct timeval last; - off_t size; - off_t offset; - off_t rcvd; - const char *name; -}; - -/* - * Compute and display ETA - */ -static const char * -stat_eta(struct xferstat *xsp) -{ - static char str[16]; - long elapsed, eta; - off_t received, expected; - - elapsed = xsp->last.tv_sec - xsp->start.tv_sec; - received = xsp->rcvd - xsp->offset; - expected = xsp->size - xsp->rcvd; - eta = (long)(elapsed * expected / received); - if (eta > 3600) - snprintf(str, sizeof str, "%02ldh%02ldm", - eta / 3600, (eta % 3600) / 60); - else - snprintf(str, sizeof str, "%02ldm%02lds", - eta / 60, eta % 60); - return str; -} - -/** High precision double comparison - * \param[in] a The first double to compare - * \param[in] b The second double to compare - * \return true on equal within precison, false if not equal within defined precision. - */ -static inline bool -compare_double(const double a, const double b) -{ - const double precision = 0.00001; - - if ((a - precision) < b && (a + precision) > b) - return true; - else - return false; -} - -/* - * Compute and display transfer rate - */ -static const char * -stat_bps(struct xferstat *xsp) -{ - static char str[16]; - char size[8]; - double delta, bps; - - delta = (xsp->last.tv_sec + (xsp->last.tv_usec / 1.e6)) - - (xsp->start.tv_sec + (xsp->start.tv_usec / 1.e6)); - if (compare_double(delta, 0.0001)) { - snprintf(str, sizeof str, "-- stalled --"); - } else { - bps = ((double)(xsp->rcvd - xsp->offset) / delta); - (void)xbps_humanize_number(size, (int64_t)bps); - snprintf(str, sizeof str, "%s/s", size); - } - return str; -} - -/* - * Update the stats display - */ -static void -stat_display(struct xferstat *xsp) -{ - struct timeval now; - char totsize[8], recvsize[8]; - - gettimeofday(&now, NULL); - if (now.tv_sec <= xsp->last.tv_sec) - return; - xsp->last = now; - - (void)xbps_humanize_number(totsize, (int64_t)xsp->size); - (void)xbps_humanize_number(recvsize, (int64_t)xsp->rcvd); - fprintf(stderr, "\r%s: %s [%d%% of %s]", - xsp->name, recvsize, - (int)((double)(100.0 * (double)xsp->rcvd) / (double)xsp->size), - totsize); - fprintf(stderr, " %s", stat_bps(xsp)); - if (xsp->size > 0 && xsp->rcvd > 0 && - xsp->last.tv_sec >= xsp->start.tv_sec + 10) - fprintf(stderr, " ETA: %s", stat_eta(xsp)); - fprintf(stderr, "\033[K"); -} - -/* - * Initialize the transfer statistics - */ -static void -stat_start(struct xferstat *xsp, const char *name, off_t *size, off_t *offset) -{ - gettimeofday(&xsp->start, NULL); - xsp->last.tv_sec = xsp->last.tv_usec = 0; - xsp->name = name; - xsp->size = *size; - xsp->offset = *offset; - xsp->rcvd = *offset; -} - -/* - * Update the transfer statistics - */ -static void -stat_update(struct xferstat *xsp, off_t rcvd) -{ - xsp->rcvd = rcvd + xsp->offset; - stat_display(xsp); -} - -/* - * Finalize the transfer statistics - */ -static void -stat_end(struct xferstat *xsp) -{ - char size[8]; - - (void)xbps_humanize_number(size, (int64_t)xsp->size); - fprintf(stderr, "\rDownloaded %s for %s [avg rate: %s]", - size, xsp->name, stat_bps(xsp)); - fprintf(stderr, "\033[K\n"); -} - -#ifdef DEBUG static const char * print_time(time_t *t) { @@ -197,13 +61,6 @@ print_time(time_t *t) strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm); return buf; } -#endif - -const char * -xbps_fetch_error_string(void) -{ - return fetchLastErrString; -} void HIDDEN xbps_fetch_set_cache_connection(int global, int per_host) @@ -222,18 +79,27 @@ xbps_fetch_unset_cache_connection(void) fetchConnectionCacheClose(); } +const char * +xbps_fetch_error_string(void) +{ + return fetchLastErrString; +} + int -xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, - const char *flags) +xbps_fetch_file(const char *uri, + const char *outputdir, + bool refetch, + const char *flags, + void (*progress_cb)(void *), + struct xbps_fetch_progress_data *xfpd) { struct stat st; - struct xferstat xs; struct url *url = NULL; struct url_stat url_st; struct fetchIO *fio = NULL; struct timeval tv[2]; + off_t bytes_dload = -1; ssize_t bytes_read = -1, bytes_written; - off_t bytes_dld = -1; char buf[4096], *filename, *destfile = NULL; int fd = -1, rv = 0; bool restart = false; @@ -244,11 +110,10 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, /* * Get the filename specified in URI argument. */ - filename = strrchr(uri, '/'); - if (filename == NULL) { - errno = EINVAL; + if ((filename = strrchr(uri, '/')) == NULL) return -1; - } + + /* Skip first '/' */ filename++; /* * Compute destination file path. @@ -261,7 +126,6 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, /* * Check if we have to resume a transfer. */ - memset(&st, 0, sizeof(st)); if (stat(destfile, &st) == 0) { if (st.st_size > 0) restart = true; @@ -324,23 +188,23 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, url->offset = st.st_size; fio = fetchXGet(url, &url_st, flags); } -#ifdef DEBUG - printf("st.st_size: %zd\n", (ssize_t)st.st_size); - printf("st.st_atime: %s\n", print_time(&st.st_atime)); - printf("st.st_mtime: %s\n", print_time(&st.st_mtime)); - printf("url->scheme: %s\n", url->scheme); - printf("url->host: %s\n", url->host); - printf("url->port: %d\n", url->port); - printf("url->doc: %s\n", url->doc); - printf("url->offset: %zd\n", (ssize_t)url->offset); - printf("url->length: %zu\n", url->length); - printf("url->last_modified: %s\n", print_time(&url->last_modified)); + /* debug stuff */ + xbps_dbg_printf("st.st_size: %zd\n", (ssize_t)st.st_size); + xbps_dbg_printf("st.st_atime: %s\n", print_time(&st.st_atime)); + xbps_dbg_printf("st.st_mtime: %s\n", print_time(&st.st_mtime)); + xbps_dbg_printf("url->scheme: %s\n", url->scheme); + xbps_dbg_printf("url->host: %s\n", url->host); + xbps_dbg_printf("url->port: %d\n", url->port); + xbps_dbg_printf("url->doc: %s\n", url->doc); + xbps_dbg_printf("url->offset: %zd\n", (ssize_t)url->offset); + xbps_dbg_printf("url->length: %zu\n", url->length); + xbps_dbg_printf("url->last_modified: %s\n", + print_time(&url->last_modified)); + xbps_dbg_printf("url_stat.size: %zd\n", (ssize_t)url_st.size); + xbps_dbg_printf("url_stat.atime: %s\n", print_time(&url_st.atime)); + xbps_dbg_printf("url_stat.mtime: %s\n", print_time(&url_st.mtime)); - printf("url_stat.size: %zd\n", (ssize_t)url_st.size); - printf("url_stat.atime: %s\n", print_time(&url_st.atime)); - printf("url_stat.mtime: %s\n", print_time(&url_st.mtime)); -#endif if (fio == NULL && fetchLastErrCode != FETCH_OK) { if (!refetch && restart && fetchLastErrCode == FETCH_UNAVAIL) { /* @@ -356,13 +220,13 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, goto out; } if (url_st.size == -1) { - printf("Remote file size is unknown!\n"); + xbps_error_printf("Remote file size is unknown!\n"); errno = EINVAL; rv = -1; goto out; } else if (st.st_size > url_st.size) { - printf("Local file %s is greater than remote file!\n", - filename); + xbps_error_printf("Local file %s is greater than remote " + "file!\n", filename); errno = EFBIG; rv = -1; goto out; @@ -371,8 +235,6 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, /* Local and remote size/mtime match, do nothing. */ goto out; } - fprintf(stderr, "Connected to %s.\n", url->host); - /* * If restarting, open the file for appending otherwise create it. */ @@ -386,32 +248,64 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, goto out; } + /* + * Initialize data for the fetch progress function callback + * and let the user know that the transfer is going to start + * immediately. + */ + if (progress_cb != NULL && xfpd != NULL) { + xfpd->file_name = filename; + xfpd->file_size = url_st.size; + xfpd->file_offset = url->offset; + xfpd->file_dloaded = -1; + xfpd->cb_start = true; + xfpd->cb_update = false; + xfpd->cb_end = false; + progress_cb(xfpd); + } /* * Start fetching requested file. */ - stat_start(&xs, filename, &url_st.size, &url->offset); while ((bytes_read = fetchIO_read(fio, buf, sizeof(buf))) > 0) { bytes_written = write(fd, buf, (size_t)bytes_read); if (bytes_written != bytes_read) { - fprintf(stderr, "Couldn't write to %s!\n", destfile); + xbps_error_printf("Couldn't write to %s!\n", destfile); rv = -1; goto out; } - bytes_dld += bytes_read; - stat_update(&xs, bytes_dld); + bytes_dload += bytes_read; + /* + * Let the fetch progress callback know that + * we are sucking more bytes from it. + */ + if (progress_cb != NULL && xfpd != NULL) { + xfpd->file_dloaded = bytes_dload; + xfpd->cb_start = false; + xfpd->cb_update = true; + progress_cb(xfpd); + } + + } + /* + * Let the fetch progress callback know that the file + * has been fetched. + */ + if (progress_cb != NULL && xfpd != NULL) { + xfpd->cb_update = false; + xfpd->cb_end = true; + progress_cb(xfpd); } if (bytes_read == -1) { - fprintf(stderr, "IO error while fetching %s: %s\n", filename, + xbps_error_printf("IO error while fetching %s: %s\n", filename, fetchLastErrString); errno = EIO; rv = -1; goto out; } - stat_end(&xs); - - if (fd == -1) + if (fd == -1) { + rv = -1; goto out; - + } /* * Update mtime in local file to match remote file if transfer * was successful. @@ -419,13 +313,14 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, tv[0].tv_sec = url_st.atime ? url_st.atime : url_st.mtime; tv[1].tv_sec = url_st.mtime; tv[0].tv_usec = tv[1].tv_usec = 0; - if (utimes(destfile, tv) == -1) + if (utimes(destfile, tv) == -1) { rv = -1; - else { - /* File downloaded successfully */ - rv = 1; + goto out; } + /* File downloaded successfully */ + rv = 1; + out: if (fd != -1) (void)close(fd); diff --git a/lib/initend.c b/lib/initend.c index cd52616a..3965bdaa 100644 --- a/lib/initend.c +++ b/lib/initend.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2010 Juan Romero Pardines. + * Copyright (c) 2011 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -50,18 +50,13 @@ xbps_end(void) xbps_fetch_unset_cache_connection(); } -void -xbps_dbg_printf(const char *fmt, ...) +static void +common_printf(FILE *f, const char *msg, const char *fmt, va_list ap) { - va_list ap; + if (msg != NULL) + fprintf(f, "%s", msg); - if (!with_debug) - return; - - va_start(ap, fmt); - fprintf(stderr, "[DEBUG] "); - vfprintf(stderr, fmt, ap); - va_end(ap); + vfprintf(f, fmt, ap); } void @@ -73,7 +68,20 @@ xbps_dbg_printf_append(const char *fmt, ...) return; va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + common_printf(stderr, NULL, fmt, ap); + va_end(ap); +} + +void +xbps_dbg_printf(const char *fmt, ...) +{ + va_list ap; + + if (!with_debug) + return; + + va_start(ap, fmt); + common_printf(stderr, "[DEBUG] ", fmt, ap); va_end(ap); } @@ -83,7 +91,30 @@ xbps_error_printf(const char *fmt, ...) va_list ap; va_start(ap, fmt); - fprintf(stderr, "ERROR: "); - vfprintf(stderr, fmt, ap); + common_printf(stderr, "ERROR: ", fmt, ap); + va_end(ap); +} + +void +xbps_warn_printf(const char *fmt, ...) +{ + int flags = xbps_get_flags(); + va_list ap; + + if ((flags & XBPS_FLAG_VERBOSE) == 0) + return; + + va_start(ap, fmt); + common_printf(stderr, "WARNING: ", fmt, ap); + va_end(ap); +} + +void +xbps_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + common_printf(stdout, NULL, fmt, ap); va_end(ap); } diff --git a/lib/package_config_files.c b/lib/package_config_files.c index 41e14fcd..9902cb16 100644 --- a/lib/package_config_files.c +++ b/lib/package_config_files.c @@ -199,7 +199,7 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd, } else if ((strcmp(sha256_orig, sha256_cur) == 0) && (strcmp(sha256_orig, sha256_new)) && (strcmp(sha256_cur, sha256_new))) { - printf("Updating configuration file `%s' " + xbps_printf("Updating configuration file `%s' " "with new version.\n", cffile); rv = 1; break; @@ -211,7 +211,7 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd, } else if ((strcmp(sha256_orig, sha256_new) == 0) && (strcmp(sha256_cur, sha256_new)) && (strcmp(sha256_orig, sha256_cur))) { - printf("Keeping modified configuration file " + xbps_printf("Keeping modified configuration file " "`%s'.\n", cffile); rv = 0; break; @@ -241,9 +241,9 @@ xbps_entry_install_conf_file(prop_dictionary_t filesd, rv = -1; break; } - printf("Keeping modified configuration file " + xbps_printf("Keeping modified configuration file " "`%s'.\n", cffile); - printf("Installing new configuration file as " + xbps_printf("Installing new configuration file as " "`%s.new-%s'\n", cffile, version); archive_entry_set_pathname(entry, buf); free(buf); diff --git a/lib/package_configure.c b/lib/package_configure.c index aecfe72a..7b89a017 100644 --- a/lib/package_configure.c +++ b/lib/package_configure.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2010 Juan Romero Pardines. + * Copyright (c) 2009-2011 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -115,7 +115,7 @@ xbps_configure_pkg(const char *pkgname, lver = version; } - printf("%sonfiguring package %s-%s...\n", + xbps_printf("%sonfiguring package `%s-%s' ...\n", reconfigure ? "Rec" : "C", pkgname, lver); buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", @@ -134,8 +134,8 @@ xbps_configure_pkg(const char *pkgname, if (xbps_file_exec(buf, "post", pkgname, lver, update ? "yes" : "no", NULL) != 0) { free(buf); - xbps_dbg_printf("%s: [configure] post INSTALL " - "action returned %s\n", pkgname, strerror(errno)); + xbps_error_printf("%s: post install script error: %s\n", + pkgname, strerror(errno)); return errno; } } else { diff --git a/lib/package_purge.c b/lib/package_purge.c index 3ef78a8c..847e7305 100644 --- a/lib/package_purge.c +++ b/lib/package_purge.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2010 Juan Romero Pardines. + * Copyright (c) 2009-2011 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ remove_pkg_metadata(const char *pkgname) struct dirent *dp; DIR *dirp; char *metadir, *path; - int rv = 0, flags = xbps_get_flags(); + int rv = 0; assert(pkgname != NULL); @@ -81,11 +81,10 @@ remove_pkg_metadata(const char *pkgname) return ENOMEM; } - if (unlink(path) == -1) { - if (flags & XBPS_FLAG_VERBOSE) - printf("WARNING: can't remove %s (%s)\n", - pkgname, strerror(errno)); - } + if (unlink(path) == -1) + xbps_warn_printf("can't remove metadata file: " + "`%s': %s\n", dp->d_name, strerror(errno)); + free(path); } (void)closedir(dirp); @@ -130,7 +129,7 @@ int xbps_purge_pkg(const char *pkgname, bool check_state) { prop_dictionary_t dict, pkgd; - int rv = 0, flags = xbps_get_flags(); + int rv = 0; pkg_state_t state = 0; assert(pkgname != NULL); @@ -188,8 +187,7 @@ xbps_purge_pkg(const char *pkgname, bool check_state) if ((rv = xbps_unregister_pkg(pkgname)) != 0) goto out; - if (flags & XBPS_FLAG_VERBOSE) - printf("Package %s purged successfully.\n", pkgname); + xbps_printf("Package %s purged successfully.\n", pkgname); out: xbps_regpkgdb_dictionary_release(); diff --git a/lib/package_remove.c b/lib/package_remove.c index 847ab38f..e9dd7f4c 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2010 Juan Romero Pardines. + * Copyright (c) 2009-2011 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -123,31 +123,28 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) "sha256", &sha256); rv = xbps_check_file_hash(path, sha256); if (rv == ENOENT) { - fprintf(stderr, - "WARNING: '%s' doesn't exist!\n", file); + xbps_warn_printf("'%s' doesn't exist!\n", file); free(path); rv = 0; continue; } else if (rv == ERANGE) { rv = 0; - if (flags & XBPS_FLAG_VERBOSE) { - if (flags & XBPS_FLAG_FORCE) { - fprintf(stderr, - "WARNING: '%s' SHA256 " - "mismatch, forcing " - "removal...\n", file); - } else { - fprintf(stderr, - "WARNING: '%s' SHA256 " - "mismatch, preserving...\n", - file); - } + if (flags & XBPS_FLAG_FORCE) { + xbps_warn_printf("'%s': SHA256 " + "mismatch, forcing removal...\n", + file); + } else { + xbps_warn_printf("'%s': SHA256 " + "mismatch, preserving file...\n", + file); } if ((flags & XBPS_FLAG_FORCE) == 0) { free(path); continue; } } else if (rv != 0 && rv != ERANGE) { + xbps_error_printf("failed to check hash for " + "`%s': %s\n", file, strerror(rv)); free(path); break; } @@ -156,15 +153,12 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) * Remove the object if possible. */ if (remove(path) == -1) { - if (flags & XBPS_FLAG_VERBOSE) - fprintf(stderr, - "WARNING: can't remove %s %s " - "(%s)\n", curobj, file, strerror(errno)); + xbps_warn_printf("can't remove %s `%s': %s\n", + curobj, file, strerror(errno)); } else { /* Success */ - if (flags & XBPS_FLAG_VERBOSE) - printf("Removed %s: %s\n", curobj, file); + xbps_printf("Removed %s: `%s'\n", curobj, file); } free(path); } @@ -207,8 +201,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) rmfile_exists = true; if (xbps_file_exec(buf, "pre", pkgname, version, update ? "yes" : "no", NULL) != 0) { - fprintf(stderr, - "%s: prerm action target error (%s)\n", + xbps_error_printf("%s: pre remove script error: %s\n", pkgname, strerror(errno)); free(buf); return errno; @@ -265,9 +258,8 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) */ if (rmfile_exists && (xbps_file_exec(buf, "post", pkgname, version, "no", NULL) != 0)) { - fprintf(stderr, - "%s: postrm action target error (%s)\n", pkgname, - strerror(errno)); + xbps_error_printf("%s: post remove script error: %s\n", + pkgname, strerror(errno)); free(buf); return errno; } diff --git a/lib/package_remove_obsoletes.c b/lib/package_remove_obsoletes.c index f22209f7..298d6e39 100644 --- a/lib/package_remove_obsoletes.c +++ b/lib/package_remove_obsoletes.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2010 Juan Romero Pardines. + * Copyright (c) 2009-2011 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -126,14 +126,13 @@ again: * Obsolete obj found, remove it. */ if (remove(file) == -1) { - fprintf(stderr, - "WARNING: couldn't remove obsolete obj: %s (%s)\n", - prop_string_cstring_nocopy(oldstr), + xbps_warn_printf("couldn't remove obsole entry " + "`%s': %s\n", prop_string_cstring_nocopy(oldstr), strerror(errno)); free(file); continue; } - printf("Removed obsolete obj: %s\n", + xbps_printf("Removed obsolete entry: %s\n", prop_string_cstring_nocopy(oldstr)); free(file); } diff --git a/lib/package_unpack.c b/lib/package_unpack.c index 4b692e2b..ff87ab25 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -65,9 +65,6 @@ * data type is specified on its edge, i.e string, array, integer, dictionary. */ -static void (*unpack_progress_cb)(void *); -static struct xbps_progress_data *sp_xpd; - static void set_extract_flags(int *flags, bool update) { @@ -152,27 +149,24 @@ remove_metafile(const char *file, const char *pkgname, const char *version) * archive_read_set_progress_callback() from libarchive(3) cannot be used * here because sometimes it misses some entries by unknown reasons. */ -#define RUN_PROGRESS_CB() \ -do { \ - if (unpack_progress_cb != NULL && xpd != NULL) \ - (*unpack_progress_cb)(xpd); \ +#define RUN_PROGRESS_CB() \ +do { \ + if (unpack_progress_cb != NULL && xupd != NULL) \ + (*unpack_progress_cb)(xupd); \ } while (0) -/* - * TODO: remove printfs and return appropiate errors to be interpreted by - * the consumer. - */ static int unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar, - struct xbps_progress_data *xpd, const char *pkgname, - const char *version) + const char *version, + void (*unpack_progress_cb)(void *), + struct xbps_unpack_progress_data *xupd) { prop_dictionary_t propsd, filesd, old_filesd; prop_array_t array; struct archive_entry *entry; - size_t entry_idx = 0; + size_t nmetadata = 0, entry_idx = 0; const char *rootdir, *entry_pname, *transact; char *buf; int rv, flags; @@ -195,7 +189,7 @@ unpack_archive(prop_dictionary_t pkg_repod, prop_dictionary_get_bool(pkg_repod, "preserve", &preserve); prop_dictionary_get_cstring_nocopy(pkg_repod, "trans-action", &transact); - assert(transasct != NULL); + assert(transact != NULL); if (strcmp(transact, "update") == 0) update = true; @@ -217,16 +211,14 @@ unpack_archive(prop_dictionary_t pkg_repod, while (archive_read_next_header(ar, &entry) == ARCHIVE_OK) { entry_pname = archive_entry_pathname(entry); set_extract_flags(&flags, update); - if (unpack_progress_cb != NULL && xpd != NULL) { - xpd->entry = entry_pname; - xpd->entry_size = archive_entry_size(entry); - xpd->entry_is_metadata = false; - xpd->entry_is_conf = false; + if (unpack_progress_cb != NULL && xupd != NULL) { + xupd->entry = entry_pname; + xupd->entry_size = archive_entry_size(entry); + xupd->entry_is_metadata = false; + xupd->entry_is_conf = false; } if (strcmp("./INSTALL", entry_pname) == 0) { - if (xpd != NULL) - xpd->entry_is_metadata = true; /* * Extract the INSTALL script first to execute * the pre install target. @@ -252,27 +244,29 @@ unpack_archive(prop_dictionary_t pkg_repod, strerror(rv)); goto out; } - entry_idx++; + nmetadata++; + if (xupd != NULL) { + xupd->entry_is_metadata = true; + xupd->entry_extract_count++; + } RUN_PROGRESS_CB(); continue; } else if (strcmp("./REMOVE", entry_pname) == 0) { - if (xpd != NULL) - xpd->entry_is_metadata = true; - rv = extract_metafile(ar, entry, "REMOVE", pkgname, version, true, flags); if (rv != 0) goto out; - entry_idx++; + nmetadata++; + if (xupd != NULL) { + xupd->entry_is_metadata = true; + xupd->entry_extract_count++; + } RUN_PROGRESS_CB(); continue; } else if (strcmp("./files.plist", entry_pname) == 0) { - if (xpd != NULL) - xpd->entry_is_metadata = true; - /* * Internalize this entry into a prop_dictionary * to check for obsolete files if updating a package. @@ -283,14 +277,15 @@ unpack_archive(prop_dictionary_t pkg_repod, rv = errno; goto out; } - entry_idx++; + nmetadata++; + if (xupd != NULL) { + xupd->entry_is_metadata = true; + xupd->entry_extract_count++; + } RUN_PROGRESS_CB(); continue; } else if (strcmp("./props.plist", entry_pname) == 0) { - if (xpd != NULL) - xpd->entry_is_metadata = true; - rv = extract_metafile(ar, entry, XBPS_PKGPROPS, pkgname, version, false, flags); if (rv != 0) @@ -302,7 +297,11 @@ unpack_archive(prop_dictionary_t pkg_repod, rv = errno; goto out; } - entry_idx++; + nmetadata++; + if (xupd != NULL) { + xupd->entry_is_metadata = true; + xupd->entry_extract_count++; + } RUN_PROGRESS_CB(); continue; } @@ -328,18 +327,18 @@ unpack_archive(prop_dictionary_t pkg_repod, } /* * Compute total entries in progress data, if set. - * total_entries = files + conf_files + links. + * total_entries = metadata + files + conf_files + links. */ - if (xpd != NULL && xpd->entry_total_count == -1) { - xpd->entry_total_count = 0; + if (xupd != NULL) { + xupd->entry_total_count = nmetadata; array = prop_dictionary_get(filesd, "files"); - xpd->entry_total_count += + xupd->entry_total_count += (ssize_t)prop_array_count(array); array = prop_dictionary_get(filesd, "conf_files"); - xpd->entry_total_count += + xupd->entry_total_count += (ssize_t)prop_array_count(array); array = prop_dictionary_get(filesd, "links"); - xpd->entry_total_count += + xupd->entry_total_count += (ssize_t)prop_array_count(array); } @@ -354,8 +353,8 @@ unpack_archive(prop_dictionary_t pkg_repod, /* error */ goto out; } else if (rv == 1) { - if (xpd != NULL) - xpd->entry_is_conf = true; + if (xupd != NULL) + xupd->entry_is_conf = true; rv = xbps_entry_install_conf_file(filesd, entry, entry_pname, pkgname, version); @@ -416,15 +415,14 @@ unpack_archive(prop_dictionary_t pkg_repod, pkgname, version, strerror(rv)); goto out; } else { - xbps_dbg_printf("WARNING: ignoring existing " + xbps_warn_printf("ignoring existing " "entry: %s\n", entry_pname); RUN_PROGRESS_CB(); continue; } } - - if (xpd != NULL) - xpd->entry_extract_count++; + if (xupd != NULL) + xupd->entry_extract_count++; RUN_PROGRESS_CB(); } @@ -486,19 +484,10 @@ out: } #undef RUN_PROGRESS_CB -void -xbps_unpack_binary_pkg_set_progress_cb(void (*fn)(void *), - struct xbps_progress_data *xpd) -{ - assert(fn != NULL); - assert(xpd != NULL); - - unpack_progress_cb = fn; - sp_xpd = xpd; -} - int -xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod) +xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod, + void (*unpack_progress_cb)(void *), + struct xbps_unpack_progress_data *xupd) { struct archive *ar; const char *pkgname, *version, *repoloc; @@ -538,14 +527,15 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod) /* * Set extract progress callback if specified. */ - if (unpack_progress_cb != NULL && sp_xpd != NULL) { - sp_xpd->entry_extract_count = -1; - sp_xpd->entry_total_count = -1; + if (unpack_progress_cb != NULL && xupd != NULL) { + xupd->entry_extract_count = 0; + xupd->entry_total_count = 0; } /* * Extract archive files. */ - rv = unpack_archive(pkg_repod, ar, sp_xpd, pkgname, version); + rv = unpack_archive(pkg_repod, ar, pkgname, version, + unpack_progress_cb, xupd); if (rv != 0) { xbps_error_printf("failed to unpack `%s' binpkg: %s\n", bpkg, strerror(rv)); diff --git a/lib/repository_sync_index.c b/lib/repository_sync_index.c index 20f1d43e..0a253384 100644 --- a/lib/repository_sync_index.c +++ b/lib/repository_sync_index.c @@ -82,7 +82,9 @@ xbps_get_remote_repo_string(const char *uri) * size and/or mtime match) and 1 if downloaded successfully. */ int -xbps_repository_sync_pkg_index(const char *uri) +xbps_repository_sync_pkg_index(const char *uri, + void (*progress_cb)(void *), + struct xbps_fetch_progress_data *xfpd) { struct url *url = NULL; struct utsname un; @@ -160,8 +162,9 @@ xbps_repository_sync_pkg_index(const char *uri) /* * Download pkg-index.plist file from repository. */ - if ((rv = xbps_fetch_file(rpidx, fetch_outputdir, - true, NULL)) == -1) { + rv = xbps_fetch_file(rpidx, fetch_outputdir, true, NULL, + progress_cb, xfpd); + if (rv == -1) { (void)remove(tmp_metafile); goto out; }