#!/dcs/bin/python

import sys
import posix
import posixpath
import string
import stat
import md5
import pwd
import grp

def traverse(devs,file='.',priorpath=''):
    if priorpath[0:2] == '//':
        priorpath=priorpath[1:]
    # lstat_ok logic prevents trying crashes due to stat'ing a file
    # that was there "just a minute ago"
    try:
        s = posix.lstat(file)
        lstat_ok = 1
    except:
        lstat_ok = 0
    if lstat_ok:
        # if not in a desired device, stop descending
        if not devs.has_key(s[stat.ST_DEV]):
            return
        if stat.S_ISDIR(s[stat.ST_MODE]):
            # recurse
            posix.chdir(file)
            files = posix.listdir('.')
            files.sort()
            for filename in files:
                if filename <> '.' and filename <> '..':
                    traverse(devs,filename,priorpath+file+'/')
            if file <> '.':
                # only backup a level, if we actually descended a level previously!
                # otherwise, we chmod something a level too high in the tree...
                posix.chdir('..')
        if stat.S_ISREG(s[stat.ST_MODE]):
            sys.stdout.write('s ')
        elif stat.S_ISLNK(s[stat.ST_MODE]):
            sys.stdout.write('l ')
        else:
            sys.stdout.write('u ')
        try:
            user=pwd.getpwuid(s[stat.ST_UID])[0]
        except:
            user=str(s[stat.ST_UID])
        sys.stdout.write(user+' ')
        try:
            group=grp.getgrgid(s[stat.ST_GID])[0]
        except:
            group=str(s[stat.ST_GID])
        sys.stdout.write(group+' '+oct(s[stat.ST_MODE])+' ')
        if stat.S_ISREG(s[stat.ST_MODE]):
            m = md5.md5()
            f = open(file,'r')
            while 1:
                block = f.read(2**18)
                if not block:
                    break
                m.update(block)
            sys.stdout.write(string_to_hex(m.digest())+' ')
        elif stat.S_ISLNK(s[stat.ST_MODE]):
            sys.stdout.write(posix.readlink(file)+' ')
        sys.stdout.write(priorpath+file+'\n')

def string_to_hex(s):
    s2 = ''
    for ch in s:
        c = ord(ch)
        if c >= 16:
            s2 = s2 + hex(c)[2:]
        else:
            s2 = s2 + '0' + hex(c)[2:]
    return s2

def main():
    devs = {}
    print string.join(posix.uname())
    for dir in ['/', '/usr', '/var', '/opt', '/usr/kvm']:
        stat_ok = 1
        try:
            # stat, not lstat, in case, EG, /var is symlinked somewhere weird
            s = posix.stat(dir)
        except:
            stat_ok = 0
        if stat_ok:
            devs[s[stat.ST_DEV]] = ''
    posix.chdir('/')
    traverse(devs,'/')
    print 'done'

main()