mirror of https://github.com/roytam1/UXP
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
6.1 KiB
158 lines
6.1 KiB
#!/usr/bin/python |
|
# This Source Code Form is subject to the terms of the Mozilla Public |
|
# License, v. 2.0. If a copy of the MPL was not distributed with this |
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
|
|
from __future__ import with_statement |
|
|
|
from optparse import OptionParser |
|
import logging |
|
import os |
|
try: |
|
import hashlib |
|
except: |
|
hashlib = None |
|
|
|
def digest_file(filename, digest, chunk_size=1024): |
|
'''Produce a checksum for the file specified by 'filename'. 'filename' |
|
is a string path to a file that is opened and read in this function. The |
|
checksum algorithm is specified by 'digest' and is a valid OpenSSL |
|
algorithm. If the digest used is not valid or Python's hashlib doesn't |
|
work, the None object will be returned instead. The size of blocks |
|
that this function will read from the file object it opens based on |
|
'filename' can be specified by 'chunk_size', which defaults to 1K''' |
|
assert not os.path.isdir(filename), 'this function only works with files' |
|
logger = logging.getLogger('checksums.py') |
|
if hashlib is not None: |
|
logger.debug('Creating new %s object' % digest) |
|
h = hashlib.new(digest) |
|
with open(filename, 'rb') as f: |
|
while True: |
|
data = f.read(chunk_size) |
|
if not data: |
|
logger.debug('Finished reading in file') |
|
break |
|
h.update(data) |
|
hash = h.hexdigest() |
|
logger.debug('Hash for %s is %s' % (filename, hash)) |
|
return hash |
|
else: |
|
# In this case we could subprocess.Popen and .communicate with |
|
# sha1sum or md5sum |
|
logger.warn('The python module for hashlib is missing!') |
|
return None |
|
|
|
|
|
def process_files(files, output_filename, digests, strip): |
|
'''This function takes a list of file names, 'files'. It will then |
|
compute the checksum for each of the files by opening the files. |
|
Once each file is read and its checksum is computed, this function |
|
will write the information to the file specified by 'output_filename'. |
|
The path written in the output file will have anything specified by 'strip' |
|
removed from the path. The output file is closed before returning nothing |
|
The algorithm to compute checksums with can be specified by 'digests' |
|
and needs to be a list of valid OpenSSL algorithms. |
|
|
|
The output file is written in the format: |
|
<hash> <algorithm> <filesize> <filepath> |
|
Example: |
|
d1fa09a<snip>e4220 sha1 14250744 firefox-4.0b6pre.en-US.mac64.dmg |
|
''' |
|
|
|
logger = logging.getLogger('checksums.py') |
|
if os.path.exists(output_filename): |
|
logger.debug('Overwriting existing checksums file "%s"' % |
|
output_filename) |
|
else: |
|
logger.debug('Creating a new checksums file "%s"' % output_filename) |
|
with open(output_filename, 'w+') as output: |
|
for file in files: |
|
if os.path.isdir(file): |
|
logger.warn('%s is a directory, skipping' % file) |
|
else: |
|
for digest in digests: |
|
hash = digest_file(file, digest) |
|
if hash is None: |
|
logger.warn('Unable to generate a hash for %s. ' + |
|
'Skipping.' % file) |
|
continue |
|
if file.startswith(strip): |
|
short_file = file[len(strip):] |
|
short_file = short_file.lstrip('/') |
|
else: |
|
short_file = file |
|
print >>output, '%s %s %s %s' % (hash, digest, |
|
os.path.getsize(file), |
|
short_file) |
|
|
|
def setup_logging(level=logging.DEBUG): |
|
'''This function sets up the logging module using a speficiable logging |
|
module logging level. The default log level is DEBUG. |
|
|
|
The output is in the format: |
|
<level> - <message> |
|
Example: |
|
DEBUG - Finished reading in file |
|
''' |
|
|
|
logger = logging.getLogger('checksums.py') |
|
logger.setLevel(logging.DEBUG) |
|
handler = logging.StreamHandler() |
|
handler.setLevel(level) |
|
formatter = logging.Formatter("%(levelname)s - %(message)s") |
|
handler.setFormatter(formatter) |
|
logger.addHandler(handler) |
|
|
|
def main(): |
|
'''This is a main function that parses arguments, sets up logging |
|
and generates a checksum file''' |
|
# Parse command line arguments |
|
parser = OptionParser() |
|
parser.add_option('-d', '--digest', help='checksum algorithm to use', |
|
action='append', dest='digests') |
|
parser.add_option('-o', '--output', help='output file to use', |
|
action='store', dest='outfile', default='checksums') |
|
parser.add_option('-v', '--verbose', |
|
help='Be noisy (takes precedence over quiet)', |
|
action='store_true', dest='verbose', default=False) |
|
parser.add_option('-q', '--quiet', help='Be quiet', action='store_true', |
|
dest='quiet', default=False) |
|
parser.add_option('-s', '--strip', |
|
help='strip this path from the filenames', |
|
dest='strip', default=os.getcwd()) |
|
options, args = parser.parse_args() |
|
|
|
#Figure out which logging level to use |
|
if options.verbose: |
|
loglevel = logging.DEBUG |
|
elif options.quiet: |
|
loglevel = logging.ERROR |
|
else: |
|
loglevel = logging.INFO |
|
|
|
#Set up logging |
|
setup_logging(loglevel) |
|
logger = logging.getLogger('checksums.py') |
|
|
|
# Validate the digest type to use |
|
if not options.digests: |
|
options.digests = ['sha1'] |
|
try: |
|
for digest in options.digests: |
|
hashlib.new(digest) |
|
except ValueError, ve: |
|
logger.error('Could not create a "%s" hash object (%s)' % |
|
(digest, ve.args[0])) |
|
exit(1) |
|
|
|
# Validate the files to checksum |
|
files = [] |
|
for i in args: |
|
if os.path.exists(i): |
|
files.append(i) |
|
else: |
|
logger.info('File "%s" was not found on the filesystem' % i) |
|
process_files(files, options.outfile, options.digests, options.strip) |
|
|
|
if __name__ == '__main__': |
|
main()
|
|
|