183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# !/usr/bin/env python 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""Guess which db package to use to open a db file.""" 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport os 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport struct 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtry: 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import dbm 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _dbmerror = dbm.error 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexcept ImportError: 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dbm = None 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # just some sort of valid exception which might be raised in the 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # dbm test 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _dbmerror = IOError 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef whichdb(filename): 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """Guess which db package to use to open a db file. 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Return values: 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh - None if the database file can't be read; 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh - empty string if the file can be read but can't be recognized 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh - the module name (e.g. "dbm" or "gdbm") if recognized. 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh Importing the given module may still fail, and opening the 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh database using that module may still fail. 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Check for dbm first -- this has a .pag and a .dir file 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(filename + os.extsep + "pag", "rb") 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # dbm linked with gdbm on OS/2 doesn't have .dir file 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"): 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(filename + os.extsep + "dir", "rb") 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "dbm" 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except IOError: 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # some dbm emulations based on Berkeley DB generate a .db file 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # some do not, but they should be caught by the dbhash checks 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(filename + os.extsep + "db", "rb") 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # guarantee we can actually open the file using dbm 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # kind of overkill, but since we are dealing with emulations 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # it seems like a prudent step 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if dbm is not None: 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh d = dbm.open(filename) 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh d.close() 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "dbm" 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except (IOError, _dbmerror): 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Check for dumbdbm next -- this has a .dir and a .dat file 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # First check for presence of files 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh os.stat(filename + os.extsep + "dat") 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh size = os.stat(filename + os.extsep + "dir").st_size 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # dumbdbm files with no keys are empty 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if size == 0: 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "dumbdbm" 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(filename + os.extsep + "dir", "rb") 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if f.read(1) in ("'", '"'): 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "dumbdbm" 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh finally: 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except (OSError, IOError): 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # See if the file exists, return None if not 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(filename, "rb") 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except IOError: 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return None 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Read the start of the file -- the magic number 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s16 = f.read(16) 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh s = s16[0:4] 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Return "" if not at least 4 bytes 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(s) != 4: 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "" 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Convert to 4-byte int in native byte order -- return "" if impossible 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (magic,) = struct.unpack("=l", s) 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "" 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Check for GNU dbm 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if magic in (0x13579ace, 0x13579acd, 0x13579acf): 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "gdbm" 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Check for old Berkeley db hash file format v2 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if magic in (0x00061561, 0x61150600): 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "bsddb185" 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Later versions of Berkeley db hash file have a 12-byte pad in 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # front of the file type 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh (magic,) = struct.unpack("=l", s16[-4:]) 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "" 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Check for BSD hash 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if magic in (0x00061561, 0x61150600): 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "dbhash" 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Unknown 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return "" 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == "__main__": 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for filename in sys.argv[1:]: 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print whichdb(filename) or "UNKNOWN", filename 118