#!/usr/bin/env python # -*- coding: iso-8859-1 -*- # This is jcfilesize. # For more information, see http://www.lysator.liu.se/~jc/jcfilesize.html # Copyright (C) 2005 Jörgen Cederlöf # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. from __future__ import division VERSION = 0.5 import sys def l2h(l): prefixes = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"] s, i = [], 0 while l: if l%1024: if i < len(prefixes): p = prefixes[i] else: p = "*1024^%d" % i s.append("%d %s" % (l%1024, p)) l //= 1024 i += 1 return " + ".join(s[::-1]) def l2hn(l): i = 1 while l > i: i *= 2 return "%s - ( %s )" % (l2h(i), l2h(i-l) or 0) def prettyl(l): return "%d bytes == 0x%X bytes == %s == %s" % (l, l, l2h(l), l2hn(l)) def testlen(f, l, test): """Return True if position l in file f is not the end of the file.""" try: f.seek(l) if f.read(1) == "": return False except IOError: return False except OverflowError: print "File is too large to measure." sys.exit(2) if test[0] == "zeros": # Consider this the end of file if we find a single non-zero # byte. for c in f.read(test[1]): if c != '\x00': return False elif test[0] == "notzeros": # Consider this the end of file if all bytes are zero. for c in f.read(test[1]): if c != '\x00': return True return False return True def main(argv): def usage(e=0): print 'This is jcfilesize version %s.' % VERSION print 'Usage: %s filename ["zeros"|"notzeros" [blocksize]]' % argv[0] sys.exit(e) if len(argv) == 2 and argv[1] in ('--help', '-h'): usage() if len(argv) >= 2: filename = argv[1] if filename == '-': f = sys.stdin else: f = open(filename) else: usage(1) t = "File length" if len(argv) >= 3: test=argv[2] if test == "zeros": t = "Length of zeros at beginning of file" elif test == "notzeros": t = "Length before all zeros" else: usage(1) else: test = "end" if len(argv) >= 4: test = (test, int(argv[3])) else: test = (test, 1024) if not testlen(f, 0, test): print t + " is exactly zero." sys.exit(0) l = 1 while True: if not testlen(f, l, test): break l *= 2 toohigh, toolow = l, l//2 while toolow+1 < toohigh: middle = (toohigh+toolow)//2 if not testlen(f, middle, test): toohigh = middle else: toolow = middle print t + ": %s" % prettyl(toohigh) if __name__ == "__main__": main(sys.argv)