xbps/bin/xbps-fetch/main.c
oopsbagel 0158000c03
bin/xbps-fetch: fix unreachable fetch result code
This commit restores the formerly unreachable code path handling the
case where the local file is identical with the remote file.

Fixes bug introduced in 66f84a8b59
2022-06-21 15:32:04 +02:00

189 lines
4.8 KiB
C

/*-
* Copyright (c) 2019 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <openssl/sha.h>
#include <xbps.h>
#include "../xbps-install/defs.h"
static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-fetch [options] <url> <url+N>\n\n"
"OPTIONS\n"
" -d, --debug Enable debug messages to stderr\n"
" -h, --help Show usage\n"
" -o, --out <file> Rename downloaded file to <file>\n"
" -s, --sha256 Output sha256sums of the files\n"
" -v, --verbose Enable verbose output\n"
" -V, --version Show XBPS version\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
static char *
fname(char *url)
{
char *filename;
if ((filename = strrchr(url, '>'))) {
*filename = '\0';
} else {
filename = strrchr(url, '/');
}
if (filename == NULL)
return NULL;
return filename + 1;
}
static void
print_digest(const uint8_t *digest, size_t len)
{
while (len--) {
if (*digest / 16 < 10)
putc('0' + *digest / 16, stdout);
else
putc('a' + *digest / 16 - 10, stdout);
if (*digest % 16 < 10)
putc('0' + *digest % 16, stdout);
else
putc('a' + *digest % 16 - 10, stdout);
++digest;
}
}
int
main(int argc, char **argv)
{
int flags = 0, c = 0, rv = 0;
bool failure = false;
bool verbose = false;
bool shasum = false;
struct xbps_handle xh = { 0 };
struct xferstat xfer = { 0 };
const char *filename = NULL, *progname = argv[0];
const struct option longopts[] = {
{ "out", required_argument, NULL, 'o' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "sha256", no_argument, NULL, 's' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
while ((c = getopt_long(argc, argv, "o:dhsVv", longopts, NULL)) != -1) {
switch (c) {
case 'h':
usage(false);
/* NOTREACHED */
case 'o':
filename = optarg;
break;
case 'd':
flags |= XBPS_FLAG_DEBUG;
break;
case 's':
shasum = true;
break;
case 'v':
verbose = true;
break;
case 'V':
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case '?':
default:
usage(true);
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (!argc) {
usage(true);
/* NOTREACHED */
}
/*
* Initialize libxbps.
*/
xh.flags = flags;
xh.fetch_cb = fetch_file_progress_cb;
xh.fetch_cb_data = &xfer;
if ((rv = xbps_init(&xh)) != 0) {
xbps_error_printf("%s: failed to initialize libxbps: %s\n",
progname, strerror(rv));
exit(EXIT_FAILURE);
}
for (int i = 0; i < argc; i++) {
unsigned char digest[XBPS_SHA256_DIGEST_SIZE];
if (i > 0 || !filename)
filename = fname(argv[i]);
if (shasum) {
rv = xbps_fetch_file_dest_sha256(&xh, argv[i], filename, verbose ? "v" : "", digest, sizeof digest);
} else {
rv = xbps_fetch_file_dest(&xh, argv[i], filename, verbose ? "v" : "");
}
if (rv == -1) {
xbps_error_printf("%s: failed to fetch: %s: %s\n",
progname, argv[i], xbps_fetch_error_string());
failure = true;
continue;
} else if (rv == 0) {
fprintf(stderr, "%s: file is identical with remote.\n", argv[i]);
if (shasum) {
if (!xbps_file_sha256_raw(digest, sizeof digest, filename)) {
xbps_error_printf("%s: failed to hash: %s: %s\n",
progname, filename, strerror(rv));
failure = true;
continue;
}
}
}
if (shasum) {
print_digest(digest, SHA256_DIGEST_LENGTH);
printf(" %s\n", filename);
}
}
xbps_end(&xh);
exit(failure ? EXIT_FAILURE : EXIT_SUCCESS);
}