tools/userland-fetch
changeset 34 d20b10eba317
parent 18 6da6bd662127
child 42 566ce4d2ff99
equal deleted inserted replaced
33:371c8e56136d 34:d20b10eba317
       
     1 #!/usr/bin/python2.6
       
     2 #
       
     3 # CDDL HEADER START
       
     4 #
       
     5 # The contents of this file are subject to the terms of the
       
     6 # Common Development and Distribution License (the "License").
       
     7 # You may not use this file except in compliance with the License.
       
     8 #
       
     9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
    10 # or http://www.opensolaris.org/os/licensing.
       
    11 # See the License for the specific language governing permissions
       
    12 # and limitations under the License.
       
    13 #
       
    14 # When distributing Covered Code, include this CDDL HEADER in each
       
    15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    16 # If applicable, add the following below this CDDL HEADER, with the
       
    17 # fields enclosed by brackets "[]" replaced with your own identifying
       
    18 # information: Portions Copyright [yyyy] [name of copyright owner]
       
    19 #
       
    20 # CDDL HEADER END
       
    21 #
       
    22 # Copyright (c) 2010, Oracle and/or it's affiliates.  All rights reserved.
       
    23 #
       
    24 #
       
    25 # fetch.py - a file download utility
       
    26 #
       
    27 #  A simple program similiar to wget(1), but handles local file copy, ignores
       
    28 #  directories, and verifies file hashes.
       
    29 #
       
    30 
       
    31 import os
       
    32 import sys
       
    33 
       
    34 def validate(filename, hash):
       
    35 	import hashlib
       
    36 
       
    37 	try:
       
    38 		file = open(filename, 'r')
       
    39 	except IOError:
       
    40 		return False
       
    41 
       
    42 	if (hash == None):
       
    43 		return True
       
    44 
       
    45 	algorithm, value = hash.split(':')
       
    46 	try:
       
    47 		m = hashlib.new(algorithm)
       
    48 	except ValueError:
       
    49 		return False
       
    50 
       
    51 	while True:
       
    52 		block = file.read()
       
    53 		m.update(block)
       
    54 		if block == '':
       
    55 			break
       
    56 
       
    57 	return m.hexdigest() == value
       
    58 
       
    59 def download(url, filename = None, hash = None, verbose = False):
       
    60 	from urllib import splittype, urlopen
       
    61 	import hashlib
       
    62 
       
    63 	src = None
       
    64 	filename = None
       
    65 
       
    66 	#print "Downloading %s from %s" % (filename, url)
       
    67 
       
    68 	# open the download source
       
    69 	if splittype(url)[0]:
       
    70 		try:
       
    71 			src = urlopen(url)
       
    72 		except IOError:
       
    73 			return None
       
    74 		remote_name = src.geturl().split('/')[-1]
       
    75 	elif os.path.isfile(url):
       
    76 		os.symlink(url, filename)
       
    77 		return filename, filehash(filename)
       
    78 		src = open(url, 'r')
       
    79 		remote_name = url.split('/')[-1]
       
    80 	else:
       
    81 		return None
       
    82 
       
    83 	if filename == None:
       
    84 		filename = remote_name
       
    85 
       
    86 	# if we have a source to download, open a destination and copy the data
       
    87 	if src:
       
    88 		dst = open(filename, 'wb');
       
    89 		if verbose:
       
    90 			print "Downloading %s from %s" % (filename, url)
       
    91 		while True:
       
    92 			block = src.read()
       
    93 			if block == '':
       
    94 				break;
       
    95 			dst.write(block)
       
    96 		dst.close()
       
    97 
       
    98 	# return the name of the file that we downloaded the data to.
       
    99 	return filename
       
   100 
       
   101 def download_paths(search, filename):
       
   102 	tmp = os.getenv('DOWNLOAD_SEARCH_PATH')
       
   103 	if tmp:
       
   104 		search += tmp.split(' ')
       
   105 	base = os.path.basename(filename)
       
   106 
       
   107 	urls = list()
       
   108 
       
   109 	for path in search:
       
   110 		urls.append(path+'/'+base)
       
   111 
       
   112 	return urls
       
   113 
       
   114 def usage():
       
   115 	print "Usage: %s [-v|--verbose] [-f|--file (file)] [-h|--hash (hash)] --url (url)" % (sys.argv[0].split('/')[-1])
       
   116 	sys.exit(1)
       
   117 
       
   118 def main():
       
   119 	from urllib import splittype, urlopen
       
   120 	import getopt
       
   121 	import sys
       
   122 
       
   123 	# FLUSH STDOUT 
       
   124 	sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
       
   125 
       
   126 	verbose = False
       
   127 	filename = None
       
   128 	url = None
       
   129 	hash = None
       
   130 	search = list()
       
   131 
       
   132 	try:
       
   133 		opts, args = getopt.getopt(sys.argv[1:], "f:h:s:u:v",
       
   134 			["file=", "hash=", "search=", "url=", "verbose"])
       
   135 	except getopt.GetoptError, err:
       
   136 		print str(err)
       
   137 		usage()
       
   138 
       
   139 	for opt, arg in opts:
       
   140 		if opt in [ "-f", "--file" ]:
       
   141 			filename = arg
       
   142 		elif opt in [ "-h", "--hash" ]:
       
   143 			hash = arg
       
   144 		elif opt in [ "-s", "--search" ]:
       
   145 			search.append(arg)
       
   146 		elif opt in [ "-u", "--url" ]:
       
   147 			url = arg
       
   148 		elif opt in [ "-v", "--verbose" ]:
       
   149 			verbose = True
       
   150 		else:
       
   151 			assert False, "unknown option"
       
   152 
       
   153 	if url == None:
       
   154 		usage()
       
   155 
       
   156 	print "Fetching %s" % filename
       
   157 
       
   158 	if validate(filename, hash):
       
   159 		print "\tcurrent copy is ok, nothing to do"
       
   160 		sys.exit(0)
       
   161 
       
   162 	# generate a list of URLS to search for a suitable download
       
   163 	urls = download_paths(search, filename)
       
   164 	urls.append(url)
       
   165 
       
   166 	for url in urls:
       
   167 		print "\tTrying %s..." % url,
       
   168 
       
   169 		if os.path.isfile(url):
       
   170 			os.symlink(url, filename)
       
   171 		elif splittype(url)[0]:
       
   172 			if download(url, filename) == None:
       
   173 				print "failed"
       
   174 				continue
       
   175 
       
   176 		print "retrieved...",
       
   177 
       
   178 		if validate(filename, hash):
       
   179 			print "validated"
       
   180 			sys.exit(0)
       
   181 		else:
       
   182 			print "corrupt"
       
   183 
       
   184 		try:
       
   185 			os.remove(filename)
       
   186 		except OSError:
       
   187 			pass
       
   188 
       
   189 	sys.exit(1)
       
   190 
       
   191 if __name__ == "__main__":
       
   192 	main()