#!/usr/bin/python2 # program to show information that's in the database # DB LAYOUT v1.6 !!! # testvalues #CNID = 39112 #DEVICE = 2304 #INODE = 2999236 import bsddb import struct import string import getopt import sys, os def usage(): print "Browsing tool for netatalk 1.6.x CNID-Database (Berkeley DB)" print "USAGE: %s [-i|--inode ]|[-c|--cnid ] " % (sys.argv[0]) print "\t is optional, default is './.AppleDB', specify path w/o .AppleDB suffix!" print "\t--show-cnid-db shows human readable content of .AppleDB/cnid.db" print "\t--show-devino-db shows human readable content of .AppleDB/devino.db" print "\t--show-didname-db shows human readable content of .AppleDB/didname.db" print "\tWARNING: the --show-* options may output a vast amount of information!" print "\t-h|--help for help (this message)" sys.exit(1) try: opts, args = getopt.getopt(sys.argv[1:], "i:c:", ["inode", "cnid", "help", "show-cnid-db", "show-devino-db", "show-didname-db"]) except getopt.GetoptError: usage() if len(args) == 0: DB_PATH = './.AppleDB' elif len(args) == 1: DB_PATH = os.path.join (args[0] + '/.AppleDB') else: usage() didname_db = bsddb.hashopen(DB_PATH + '/didname.db', 'r') cnid_db = bsddb.hashopen(DB_PATH + '/cnid.db', 'r') devino_db = bsddb.hashopen(DB_PATH + '/devino.db', 'r') def prettyprint_didname_db(): print "%10s %10s NAME" % ('DID', 'CNID') i = 0 while i == 0: try: key, value = didname_db.next() except KeyError: i = 1 print "%10s %10s '%s'" % (struct.unpack (">I", key[:4])[0], struct.unpack(">I", value)[0], key[4:-1]) def prettyprint_cnid_db(): print "%10s %10s %10s %10s NAME" % ('CNID', 'DEV', 'INODE', 'DID') i = 0 while i == 0: try: key, value = cnid_db.next() except KeyError: i = 1 print "%10s %10s %10s %10s '%s'" % (struct.unpack (">I", key)[0], struct.unpack (">I", value[:4])[0], struct.unpack (">I", value[4:8])[0], struct.unpack (">I", value[8:12])[0], value[12:-1]) def prettyprint_devino_db(): print "%10s %10s %10s" % ('DEV', 'INODE', 'CNID') i = 0 while i == 0: try: key, value = devino_db.next() except KeyError: i = 1 device, inode = struct.unpack (">LL", key) print "%10s %10s %10s" % (device, inode, struct.unpack(">I", value)[0]) pInode = 0 pCNID = 0 ID = 0 for o, a in opts: if o in ("-i", "--inode"): if pCNID == 0: pInode = 1 DEVICE, INODE = string.split (a, ',') DEVICE = int (DEVICE) INODE = int (INODE) else: usage() if o in ("-c", "--cnid"): if pInode == 0: pCNID = 1 CNID = a else: usage() if o == "--show-cnid-db": prettyprint_cnid_db() if o == "--show-devino-db": prettyprint_devino_db if o == "--show-didname-db": prettyprint_didname_db() if o in ("-h", "--help"): usage() # returns tuple [did, filename] def getFilenameFromCNID (cnid): global cnid_db, didname_db, devino_db try: data = cnid_db.set_location(struct.pack (">L", cnid)) except KeyError: return (-1, '') return (struct.unpack(">L", data[1][8:12])[0], data[1][12:-1]) # returns path to filename def getFullPathFromCNID (cnid): did, filename = getFilenameFromCNID(cnid) fullname = filename while did != -1: did, filename = getFilenameFromCNID(did) fullname = filename + "/" + fullname return fullname if pInode: dev_inode = struct.pack (">LL", DEVICE, INODE) try: devino_data = devino_db.set_location(dev_inode) print getFullPathFromCNID (struct.unpack(">L", devino_data[1])[0]) except KeyError: sys.stderr.write ("DEVICE and INODE combination not found.\n") if pCNID: print getFullPathFromCNID (CNID)