userland-fetch revision 4427
4496171313bed39e96f21bc2f9faf2868e267ae3girish# CDDL HEADER START
4496171313bed39e96f21bc2f9faf2868e267ae3girish# The contents of this file are subject to the terms of the
4496171313bed39e96f21bc2f9faf2868e267ae3girish# Common Development and Distribution License (the "License").
4496171313bed39e96f21bc2f9faf2868e267ae3girish# You may not use this file except in compliance with the License.
4496171313bed39e96f21bc2f9faf2868e267ae3girish# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4496171313bed39e96f21bc2f9faf2868e267ae3girish# See the License for the specific language governing permissions
4496171313bed39e96f21bc2f9faf2868e267ae3girish# and limitations under the License.
4496171313bed39e96f21bc2f9faf2868e267ae3girish# When distributing Covered Code, include this CDDL HEADER in each
4496171313bed39e96f21bc2f9faf2868e267ae3girish# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4496171313bed39e96f21bc2f9faf2868e267ae3girish# If applicable, add the following below this CDDL HEADER, with the
4496171313bed39e96f21bc2f9faf2868e267ae3girish# fields enclosed by brackets "[]" replaced with your own identifying
4496171313bed39e96f21bc2f9faf2868e267ae3girish# information: Portions Copyright [yyyy] [name of copyright owner]
4496171313bed39e96f21bc2f9faf2868e267ae3girish# CDDL HEADER END
b80c1b6352b6730ba463305c5aad8ab1b7814a1fSree Vemuri# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
4496171313bed39e96f21bc2f9faf2868e267ae3girish# userland-fetch - a file download utility
4496171313bed39e96f21bc2f9faf2868e267ae3girish# A simple program similiar to wget(1), but handles local file copy, ignores
4496171313bed39e96f21bc2f9faf2868e267ae3girish# directories, and verifies file hashes.
59ac0c1669407488b67ae9e273667a340dccc611davemq """ Function to decode and print IOError type exception """
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Given paths to a file and a detached PGP signature, verify that
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu the signature is valid for the file. Current configuration allows for
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu unrecognized keys to be downloaded as necessary."""
4496171313bed39e96f21bc2f9faf2868e267ae3girish # Find the root of the repo so that we can point GnuPG at the right
4496171313bed39e96f21bc2f9faf2868e267ae3girish # configuration and keyring.
4496171313bed39e96f21bc2f9faf2868e267ae3girish proc = subprocess.Popen(["hg", "root"], stdout=subprocess.PIPE)
4496171313bed39e96f21bc2f9faf2868e267ae3girish gpgdir = os.path.join(out.strip(), "tools", ".gnupg")
4496171313bed39e96f21bc2f9faf2868e267ae3girish # Skip the permissions warning: none of the information here is private,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # so not having to worry about getting mercurial keeping the directory
4496171313bed39e96f21bc2f9faf2868e267ae3girish # unreadable is just simplest.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu "--no-permission-warning", "--homedir", gpgdir, signature,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # If the executable simply couldn't be found, just skip the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # validation.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # Only print GnuPG's output when there was a problem.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Given a file-like object and a hash string, verify that the hash
4496171313bed39e96f21bc2f9faf2868e267ae3girish matches the file contents."""
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # force migration away from sha1
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Given a file path and a hash string, verify that the hash matches the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu file contents."""
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Given a file path and a hash string, verify that the hash matches the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu payload (uncompressed content) of the file."""
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Download the content at the given URL to the given filename
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu (defaulting to the basename of the URL if not given. If 'quiet' is
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu True, throw away any error messages. Returns the name of the file to
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu which the content was donloaded."""
59ac0c1669407488b67ae9e273667a340dccc611davemq # 3xx, 4xx and 5xx (f|ht)tp codes designate unsuccessfull action
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu printIOError(e, "Can't open file " + filename + " for writing")
b80c1b6352b6730ba463305c5aad8ab1b7814a1fSree Vemuri # return the name of the file that we downloaded the data to.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Returns a list of URLs where the file 'filename' might be found,
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu using 'url', 'search', and $DOWNLOAD_SEARCH_PATH as places to look.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu If 'filename' is None, then the list will simply contain 'url'.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # filename should always be first
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu # command line url is a fallback, so it's last
b80c1b6352b6730ba463305c5aad8ab1b7814a1fSree Vemuridef download_from_paths(search_list, file_arg, url, link_arg, quiet=False):
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu """Attempts to download a file from a number of possible locations.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu Generates a list of paths where the file ends up on the local
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu filesystem. This is a generator because while a download might be
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu successful, the signature or hash may not validate, and the caller may
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu want to try again from the next location. The 'link_arg' argument is a
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu boolean which, when True, specifies that if the source is not a remote
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu URL and not already found where it should be, to make a symlink to the
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu source rather than copying it.
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri for url in download_paths(search_list, file_arg, url):
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "not found, skipping file copy"
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "\n copying..."
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "\n linking..."
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "\n downloading...",
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "failed"
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "Usage: %s [-f|--file (file)] [-l|--link] [-h|--hash (hash)] " \
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri "[-s|--search (search-dir)] [-S|--sigurl (signature-url)] --url (url)" % \
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri # FLUSH STDOUT
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri opts, args = getopt.getopt(sys.argv[1:], "f:h:ls:S:u:",
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri ["file=", "link", "hash=", "search=", "sigurl=", "url="])
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri for name in download_from_paths(search_list, file_arg, url_arg, link_arg):
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "\n validating signature...",
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri print "skipping (no signature URL)"
64cfc8ed0c5da83f827c424588bfe709e3fb5a7asvemuri # Put the signature file in the same directory as the
59ac0c1669407488b67ae9e273667a340dccc611davemq # file we're downloading.
4496171313bed39e96f21bc2f9faf2868e267ae3girish # Validate with the first signature we find.
4496171313bed39e96f21bc2f9faf2868e267ae3girish for sig_file in download_from_paths(search_list, sig_file,
4496171313bed39e96f21bc2f9faf2868e267ae3girish print "failed"
if sig_valid:
if sig_valid:
try:
name)
try: