#! /usr/bin/env python2
# $Id: dpns-du,v 1.3 2009/01/29 09:35:39 gcowan Exp $

__author__ = 'Greig A Cowan'
__date__ = 'August 2008'
__version = 0.1

'''du like utility for DPM namespace.'''

import sys

try:
    import dpm
except:
    print 'Failed to import dpm API. Check your $PYTHONPATH. If this is correct, Please check the bitness of your system libraries - it may be that you have 64bit python and 32bit DPM.'
    sys.exit(1)

import stat
from optparse import OptionParser

def main():
    parser = OptionParser(
        usage = 'usage: %prog /dpm/path/to/directory')
    parser.add_option('--si',dest='si',action='store_true',
                      help='Use powers of 1000, not 1024.')
    parser.add_option('-x','--exclude',dest='exclude',
                      help='Directory to ignore.')
    parser.add_option('-z','--zero',dest='zero', action='store_true',
                      help='Do not print out directories of 0 size.')
    parser.add_option('-s','--summary',dest='summary', action='store_true',
                      help='Display only a summary for each argument')

    (options, args) = parser.parse_args()

    directory =''
    if len(args) == 0:
	parser.print_help()
	sys.exit(1)
    else:
	directory = args[0]

    if len(args) > 1:
        parser.error("incorrect number of arguments")

    total = scan( directory, options.si, options.exclude, options.zero, options.summary)

    if options.summary:
        display( total, options.si, options.zero, directory)

def scan( directory, si, exclude, zero, summary):
    '''Scan through the directory tree.'''
    if directory == exclude:
        return 0
    if directory[-1] != '/':
        directory = directory + '/'
    dir_handle = dpm.dpns_opendirg( directory,'')
    if (dir_handle == None) or (dir_handle == 0):
        err_num = dpm.cvar.serrno
        err_string = dpm.sstrerror( err_num)
        print 'Error while looking for ' + directory + ': Error ' \
              + str(err_num) + ' (' + err_string + ')'
        sys.exit(1)

    size = 0
    while 1:
        read_pt = dpm.dpns_readdirxr( dir_handle,'')
        if ( read_pt == None) or ( read_pt == 0):
            break
        entry, list = read_pt
        if stat.S_ISREG( entry.filemode):
            size += entry.filesize
        if stat.S_ISDIR( entry.filemode):
            dir = directory + entry.d_name
            size += scan( dir, si, exclude, zero, summary)

    dpm.dpns_closedir( dir_handle)

    if not summary:
        display( size, si, zero, directory)
    return size


def display( size, si, zero, directory):
    if si:
        s, unit = convert( size, 1000) 
        if s > 0.0 or not zero:
            if s ==  0:
                print '%d%s\t %s' % ( s, unit, directory)
            else:
                print '%.2f%s\t %s' % ( s, unit, directory)
    else:
        s, unit = convert( size, 1024) 
        if s > 0.0 or not zero:
            if s ==  0:
                print '%d%s\t %s' % ( s, unit, directory)
            else:
                print '%.2f%s\t %s' % ( s, unit, directory)
    

def convert( size, factor):
        if size <= factor:
            s = float( size)/(factor**0)
            unit = 'B'
        if size > factor:
            s = float( size)/(factor**1)
            unit = 'K'
        if size > factor**2:
            s = float( size)/(factor**2)
            unit = 'M'
        if size > factor**3:
            s = float( size)/(factor**3)
            unit = 'G'
        if size > factor**4:
            s = float( size)/(factor**4)
            unit = 'T'
        if size > factor**5:
            s = float( size)/(factor**5)
            unit = 'P'

        return s, unit
    
if __name__ == '__main__':
         main()
