Some changes to know if a file was downloaded successfully or not.
Improved xbps-repo sync/add and xbps-fetch to print informative messages when a transfer was not necessary because local/remote size and/or mtime matched. --HG-- extra : convert_revision : xtraeme%40gmail.com-20091124050326-owez7140fdxwepuk
This commit is contained in:
		| @@ -177,9 +177,9 @@ download_package_list(prop_object_iterator_t iter) | ||||
| 		rv = xbps_fetch_file(binfile, savedir, false, NULL); | ||||
| 		free(savedir); | ||||
| 		free(binfile); | ||||
| 		if (rv != 0) { | ||||
| 		if (rv == -1) { | ||||
| 			printf("Couldn't download %s from %s (%s)\n", | ||||
| 			    filename, repoloc, strerror(rv)); | ||||
| 			    filename, repoloc, xbps_fetch_error_string()); | ||||
| 			free(repoloc_trans); | ||||
| 			return errno; | ||||
| 		} | ||||
|   | ||||
| @@ -33,9 +33,11 @@ main(int argc, char **argv) | ||||
| 		usage(); | ||||
|  | ||||
| 	rv = xbps_fetch_file(argv[0], ".", false, flags); | ||||
| 	if (rv != 0) { | ||||
| 	if (rv == -1) { | ||||
| 		printf("%s: %s\n", argv[0], xbps_fetch_error_string()); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} else if (rv == 0) { | ||||
| 		printf("%s: file is identical than remote.\n", argv[0]); | ||||
| 	} | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
|   | ||||
| @@ -35,13 +35,8 @@ | ||||
| #include "index.h" | ||||
| #include "util.h" | ||||
|  | ||||
| typedef struct repository_info { | ||||
| 	const char *index_version; | ||||
| 	uint64_t total_pkgs; | ||||
| } repo_info_t; | ||||
|  | ||||
| static bool sanitize_localpath(char *, const char *); | ||||
| static bool pkgindex_getinfo(prop_dictionary_t, repo_info_t *); | ||||
| static int  pkgindex_verify(const char *, const char *, bool); | ||||
| static void usage(void); | ||||
|  | ||||
| static void | ||||
| @@ -71,24 +66,54 @@ usage(void) | ||||
| 	exit(EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| static bool | ||||
| pkgindex_getinfo(prop_dictionary_t dict, repo_info_t *ri) | ||||
| static int | ||||
| pkgindex_verify(const char *plist, const char *uri, bool only_sync) | ||||
| { | ||||
| 	assert(dict != NULL || ri != NULL); | ||||
| 	prop_dictionary_t d; | ||||
| 	const char *pkgidx_version; | ||||
| 	uint64_t total_pkgs; | ||||
| 	int rv = 0; | ||||
|  | ||||
| 	if (!prop_dictionary_get_cstring_nocopy(dict, | ||||
| 	    "pkgindex-version", &ri->index_version)) | ||||
| 		return false; | ||||
| 	assert(plist != NULL); | ||||
|  | ||||
| 	if (!prop_dictionary_get_uint64(dict, "total-pkgs", | ||||
| 	    &ri->total_pkgs)) | ||||
| 		return false; | ||||
| 	d = prop_dictionary_internalize_from_file(plist); | ||||
| 	if (d == NULL) { | ||||
| 		printf("E: repository %s does not contain any " | ||||
| 		    "xbps pkgindex file.\n", uri); | ||||
| 		return errno; | ||||
| 	} | ||||
|  | ||||
| 	if (!prop_dictionary_get_cstring_nocopy(d, | ||||
| 	    "pkgindex-version", &pkgidx_version)) { | ||||
| 		printf("E: missing 'pkgindex-version' object!\n"); | ||||
| 		rv = errno; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!prop_dictionary_get_uint64(d, "total-pkgs", &total_pkgs)) { | ||||
| 		printf("E: missing 'total-pkgs' object!\n"); | ||||
| 		rv = errno; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	/* Reject empty repositories, how could this happen? :-) */ | ||||
| 	if (ri->total_pkgs <= 0) | ||||
| 		return false; | ||||
| 	if (total_pkgs == 0) { | ||||
| 		printf("E: empty package list!\n"); | ||||
| 		rv = EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| 	printf("%s package index at %s (v%s) with %ju packages.\n", | ||||
| 	    only_sync ? "Updated" : "Added", uri, pkgidx_version, total_pkgs); | ||||
|  | ||||
| out: | ||||
| 	prop_object_release(d); | ||||
| 	if (rv != 0) { | ||||
| 		printf("W: removing incorrect pkg index file: '%s' ...\n", | ||||
| 		    plist); | ||||
| 		rv = remove(plist); | ||||
| 	} | ||||
| 	return rv; | ||||
| } | ||||
|  | ||||
| static bool | ||||
| @@ -135,8 +160,6 @@ out: | ||||
| static int | ||||
| add_repository(const char *uri) | ||||
| { | ||||
| 	prop_dictionary_t dict; | ||||
| 	repo_info_t *rinfo; | ||||
| 	char *plist, idxstr[PATH_MAX]; | ||||
| 	int rv = 0; | ||||
|  | ||||
| @@ -146,10 +169,14 @@ add_repository(const char *uri) | ||||
|  | ||||
| 		printf("Fetching remote package index at %s...\n", uri); | ||||
| 		rv = xbps_sync_repository_pkg_index(idxstr); | ||||
| 		if (rv != 0) { | ||||
| 		if (rv == -1) { | ||||
| 			printf("Error: could not fetch pkg index file: %s.\n", | ||||
| 			    xbps_fetch_error_string()); | ||||
| 			return rv; | ||||
| 		} else if (rv == 0) { | ||||
| 			printf("Package index file is already " | ||||
| 			    "up to date.\n"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		plist = xbps_get_pkg_index_plist(idxstr); | ||||
| @@ -163,25 +190,8 @@ add_repository(const char *uri) | ||||
| 	if (plist == NULL) | ||||
| 		return errno; | ||||
|  | ||||
| 	dict = prop_dictionary_internalize_from_file(plist); | ||||
| 	if (dict == NULL) { | ||||
| 		printf("Repository %s does not contain any " | ||||
| 		    "xbps pkgindex file.\n", idxstr); | ||||
| 		rv = errno; | ||||
| 	if ((rv = pkgindex_verify(plist, idxstr, false)) != 0) | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	rinfo = malloc(sizeof(*rinfo)); | ||||
| 	if (rinfo == NULL) { | ||||
| 		rv = errno; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (!pkgindex_getinfo(dict, rinfo)) { | ||||
| 		printf("'%s' is incomplete.\n", plist); | ||||
| 		rv = EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if ((rv = xbps_register_repository(idxstr)) != 0) { | ||||
| 		printf("ERROR: couldn't register repository (%s)\n", | ||||
| @@ -189,14 +199,7 @@ add_repository(const char *uri) | ||||
| 		goto out; | ||||
| 	} | ||||
| 	 | ||||
| 	printf("Added repository at %s (%s) with %ju packages.\n", | ||||
| 	       idxstr, rinfo->index_version, rinfo->total_pkgs); | ||||
|  | ||||
| out: | ||||
| 	if (dict != NULL) | ||||
| 		prop_object_release(dict); | ||||
| 	if (rinfo != NULL) | ||||
| 		free(rinfo); | ||||
| 	if (plist != NULL) | ||||
| 		free(plist); | ||||
|  | ||||
| @@ -206,8 +209,8 @@ out: | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| { | ||||
| 	char dpkgidx[PATH_MAX], *root = NULL; | ||||
| 	struct repository_data *rdata = NULL; | ||||
| 	char dpkgidx[PATH_MAX], *plist, *root = NULL; | ||||
| 	int c, rv = 0; | ||||
|  | ||||
| 	while ((c = getopt(argc, argv, "Vr:")) != -1) { | ||||
| @@ -313,8 +316,22 @@ main(int argc, char **argv) | ||||
| 			if (xbps_check_is_repo_string_remote(uri)) { | ||||
| 				printf("Syncing package index from: %s\n", uri); | ||||
| 				rv = xbps_sync_repository_pkg_index(uri); | ||||
| 				if (rv != 0) | ||||
| 				if (rv == -1) { | ||||
| 					printf("Failed! returned: %s\n", | ||||
| 					    xbps_fetch_error_string()); | ||||
| 					break; | ||||
| 				} else if (rv == 0) { | ||||
| 					printf("Package index file is already " | ||||
| 					    "up to date.\n"); | ||||
| 					continue; | ||||
| 				} | ||||
| 				plist = xbps_get_pkg_index_plist(uri); | ||||
| 				if (plist == NULL) { | ||||
| 					rv = EINVAL; | ||||
| 					break; | ||||
| 				} | ||||
| 				(void)pkgindex_verify(plist, uri, true); | ||||
| 				free(plist); | ||||
| 			} | ||||
| 		} | ||||
| 		xbps_release_repolist_data(); | ||||
|   | ||||
| @@ -183,6 +183,10 @@ print_time(time_t *t) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  * Returns -1 on error, 0 if not download (because local/remote | ||||
|  * size and/or mtime match) and 1 if downloaded successfully. | ||||
|  */ | ||||
| int SYMEXPORT | ||||
| xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 		const char *flags) | ||||
| @@ -207,15 +211,17 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 	 * Get the filename specified in URI argument. | ||||
| 	 */ | ||||
| 	filename = strrchr(uri, '/'); | ||||
| 	if (filename == NULL) | ||||
| 		return EINVAL; | ||||
| 	if (filename == NULL) { | ||||
| 		errno = EINVAL; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	filename++; | ||||
| 	/* | ||||
| 	 * Compute destination file path. | ||||
| 	 */ | ||||
| 	destfile = xbps_xasprintf("%s/%s", outputdir, filename); | ||||
| 	if (destfile == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| @@ -227,7 +233,7 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 			restart = true; | ||||
| 	} else { | ||||
| 		if (errno != ENOENT) { | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| @@ -235,7 +241,7 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 	 * Prepare stuff for libfetch. | ||||
| 	 */ | ||||
| 	if ((url = fetchParseURL(uri)) == NULL) { | ||||
| 		rv = fetchLastErrCode; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
|  | ||||
| 	} | ||||
| @@ -246,10 +252,9 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 		/* | ||||
| 		 * Issue a HEAD request to know size and mtime. | ||||
| 		 */ | ||||
| 		if (fetchStat(url, &url_st, NULL) == -1) { | ||||
| 			rv = fetchLastErrCode; | ||||
| 		if ((rv = fetchStat(url, &url_st, NULL)) == -1) | ||||
| 			goto out; | ||||
| 		} | ||||
|  | ||||
| 		/* | ||||
| 		 * If mtime and size match do nothing. | ||||
| 		 */ | ||||
| @@ -268,7 +273,7 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 		 * Remove current file (if exists). | ||||
| 		 */ | ||||
| 		if (restart && remove(destfile) == -1) { | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		restart = false; | ||||
| @@ -313,22 +318,23 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 			if (url->length == 0) | ||||
| 				goto out; | ||||
| 		} | ||||
| 		rv = fetchLastErrCode; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (url_st.size == -1) { | ||||
| 		printf("Remote file size is unknown!\n"); | ||||
| 		rv = EINVAL; | ||||
| 		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); | ||||
| 		rv = EFBIG; | ||||
| 		errno = EFBIG; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} else if (restart && url_st.mtime && url_st.size && | ||||
| 		   url_st.size == st.st_size && url_st.mtime == st.st_mtime) { | ||||
| 		/* Local and remote size/mtime match, do nothing. */ | ||||
| 		rv = 0; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	fprintf(stderr, "Connected to %s.\n", url->host); | ||||
| @@ -342,7 +348,7 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 		fd = open(destfile, O_WRONLY|O_CREAT|O_TRUNC, 0644); | ||||
|  | ||||
| 	if (fd == -1) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| @@ -354,7 +360,7 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 		bytes_written = write(fd, buf, (size_t)bytes_read); | ||||
| 		if (bytes_written != bytes_read) { | ||||
| 			fprintf(stderr, "Couldn't write to %s!\n", destfile); | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 		bytes_dld += bytes_read; | ||||
| @@ -363,7 +369,8 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 	if (bytes_read == -1) { | ||||
| 		fprintf(stderr, "IO error while fetching %s: %s\n", filename, | ||||
| 		    fetchLastErrString); | ||||
| 		rv = EINVAL; | ||||
| 		errno = EIO; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	stat_end(&xs); | ||||
| @@ -379,7 +386,11 @@ xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, | ||||
| 	tv[1].tv_sec = url_st.mtime; | ||||
| 	tv[0].tv_usec = tv[1].tv_usec = 0; | ||||
| 	if (utimes(destfile, tv) == -1) | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 	else { | ||||
| 		/* File downloaded successfully */ | ||||
| 		rv = 1; | ||||
| 	} | ||||
|  | ||||
| out: | ||||
| 	if (fd != -1) | ||||
|   | ||||
| @@ -68,6 +68,10 @@ xbps_get_remote_repo_string(const char *uri) | ||||
| 	return p; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Returns -1 on error, 0 if transfer was not necessary (local/remote | ||||
|  * size and/or mtime match) and 1 if downloaded successfully. | ||||
|  */ | ||||
| int SYMEXPORT | ||||
| xbps_sync_repository_pkg_index(const char *uri) | ||||
| { | ||||
| @@ -84,15 +88,15 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	metadir = tmp_metafile = lrepofile = NULL; | ||||
|  | ||||
| 	if (uname(&un) == -1) | ||||
| 		return errno; | ||||
| 		return -1; | ||||
|  | ||||
| 	if ((url = fetchParseURL(uri)) == NULL) | ||||
| 		return errno; | ||||
| 		return -1; | ||||
|  | ||||
| 	uri_fixedp = xbps_get_remote_repo_string(uri); | ||||
| 	if (uri_fixedp == NULL) { | ||||
| 		fetchFreeURL(url); | ||||
| 		return errno; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| @@ -101,17 +105,18 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	metadir = xbps_xasprintf("%s/%s", xbps_get_rootdir(), | ||||
| 	    XBPS_META_PATH); | ||||
| 	if (metadir == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	rv = stat(metadir, &st); | ||||
| 	if (rv == -1 && errno == ENOENT) { | ||||
| 		if (mkpath(metadir, 0755) == -1) { | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} else if (rv == 0 && !S_ISDIR(st.st_mode)) { | ||||
| 		rv = ENOTDIR; | ||||
| 		errno = ENOTDIR; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| @@ -120,7 +125,7 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	 */ | ||||
| 	rpidx = xbps_xasprintf("%s/%s/%s", uri, un.machine, XBPS_PKGINDEX); | ||||
| 	if (rpidx == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| @@ -129,7 +134,7 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	 */ | ||||
| 	tmp_metafile = xbps_xasprintf("%s/%s", metadir, XBPS_PKGINDEX); | ||||
| 	if (tmp_metafile == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| @@ -138,7 +143,7 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	lrepodir = xbps_xasprintf("%s/%s/%s/%s", | ||||
| 	    xbps_get_rootdir(), XBPS_META_PATH, uri_fixedp, un.machine); | ||||
| 	if (lrepodir == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| @@ -156,7 +161,7 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	 * Download pkg-index.plist file from repository. | ||||
| 	 */ | ||||
| 	if ((rv = xbps_fetch_file(rpidx, fetch_outputdir, | ||||
| 	     true, NULL)) != 0) { | ||||
| 	     true, NULL)) == -1) { | ||||
| 		(void)remove(tmp_metafile); | ||||
| 		goto out; | ||||
| 	} | ||||
| @@ -171,11 +176,12 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	rv = stat(lrepodir, &st); | ||||
| 	if (rv == -1 && errno == ENOENT) { | ||||
| 		if (mkpath(lrepodir, 0755) == -1) { | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} else if (rv == 0 && !S_ISDIR(st.st_mode)) { | ||||
| 		rv = ENOTDIR; | ||||
| 		errno = ENOTDIR; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| @@ -186,31 +192,34 @@ xbps_sync_repository_pkg_index(const char *uri) | ||||
| 	dir = xbps_xasprintf("%s/%s/%s/noarch", | ||||
| 	    xbps_get_rootdir(), XBPS_META_PATH, uri_fixedp); | ||||
| 	if (dir == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	rv = stat(dir, &st); | ||||
| 	if (rv == -1 && errno == ENOENT) { | ||||
| 		if (mkpath(dir, 0755) == -1) { | ||||
| 			free(dir); | ||||
| 			rv = errno; | ||||
| 			rv = -1; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} else if (rv == 0 && !S_ISDIR(st.st_mode)) { | ||||
| 		free(dir); | ||||
| 		rv = ENOTDIR; | ||||
| 		errno = ENOTDIR; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	free(dir); | ||||
| 	lrepofile = xbps_xasprintf("%s/%s", lrepodir, XBPS_PKGINDEX); | ||||
| 	if (lrepofile == NULL) { | ||||
| 		rv = errno; | ||||
| 		rv = -1; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Rename to destination file now it has been fetched successfully. | ||||
| 	 */ | ||||
| 	rv = rename(tmp_metafile, lrepofile); | ||||
| 	if ((rv = rename(tmp_metafile, lrepofile)) == 0) | ||||
| 		rv = 1; | ||||
|  | ||||
| out: | ||||
| 	if (rpidx) | ||||
| 		free(rpidx); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user