#!/usr/bin/python2.6
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2010, Oracle and/or it's affiliates. All rights reserved.
#
#
# fetch.py - a file download utility
#
# A simple program similiar to wget(1), but handles local file copy, ignores
# directories, and verifies file hashes.
#
import os
import sys
def validate(filename, hash):
import hashlib
try:
file = open(filename, 'r')
except IOError:
return False
if (hash == None):
return True
algorithm, value = hash.split(':')
try:
m = hashlib.new(algorithm)
except ValueError:
return False
while True:
block = file.read()
m.update(block)
if block == '':
break
return m.hexdigest() == value
def download(url, filename = None, hash = None, verbose = False):
from urllib import splittype, urlopen
import hashlib
src = None
filename = None
#print "Downloading %s from %s" % (filename, url)
# open the download source
if splittype(url)[0]:
try:
src = urlopen(url)
except IOError:
return None
remote_name = src.geturl().split('/')[-1]
elif os.path.isfile(url):
os.symlink(url, filename)
return filename, filehash(filename)
src = open(url, 'r')
remote_name = url.split('/')[-1]
else:
return None
if filename == None:
filename = remote_name
# if we have a source to download, open a destination and copy the data
if src:
dst = open(filename, 'wb');
if verbose:
print "Downloading %s from %s" % (filename, url)
while True:
block = src.read()
if block == '':
break;
dst.write(block)
dst.close()
# return the name of the file that we downloaded the data to.
return filename
def download_paths(search, filename):
tmp = os.getenv('DOWNLOAD_SEARCH_PATH')
if tmp:
search += tmp.split(' ')
base = os.path.basename(filename)
urls = list()
for path in search:
urls.append(path+'/'+base)
return urls
def usage():
print "Usage: %s [-v|--verbose] [-f|--file (file)] [-h|--hash (hash)] --url (url)" % (sys.argv[0].split('/')[-1])
sys.exit(1)
def main():
from urllib import splittype, urlopen
import getopt
import sys
# FLUSH STDOUT
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
verbose = False
filename = None
url = None
hash = None
search = list()
try:
opts, args = getopt.getopt(sys.argv[1:], "f:h:s:u:v",
["file=", "hash=", "search=", "url=", "verbose"])
except getopt.GetoptError, err:
print str(err)
usage()
for opt, arg in opts:
if opt in [ "-f", "--file" ]:
filename = arg
elif opt in [ "-h", "--hash" ]:
hash = arg
elif opt in [ "-s", "--search" ]:
search.append(arg)
elif opt in [ "-u", "--url" ]:
url = arg
elif opt in [ "-v", "--verbose" ]:
verbose = True
else:
assert False, "unknown option"
if url == None:
usage()
print "Fetching %s" % filename
if validate(filename, hash):
print "\tcurrent copy is ok, nothing to do"
sys.exit(0)
# generate a list of URLS to search for a suitable download
urls = download_paths(search, filename)
urls.append(url)
for url in urls:
print "\tTrying %s..." % url,
if os.path.isfile(url):
os.symlink(url, filename)
elif splittype(url)[0]:
if download(url, filename) == None:
print "failed"
continue
print "retrieved...",
if validate(filename, hash):
print "validated"
sys.exit(0)
else:
print "corrupt"
try:
os.remove(filename)
except OSError:
pass
sys.exit(1)
if __name__ == "__main__":
main()