1 # !/usr/bin/env python 2 """Guess which db package to use to open a db file.""" 3 4 import os 5 import struct 6 import sys 7 8 try: 9 import dbm 10 _dbmerror = dbm.error 11 except ImportError: 12 dbm = None 13 # just some sort of valid exception which might be raised in the 14 # dbm test 15 _dbmerror = IOError 16 17 def whichdb(filename): 18 """Guess which db package to use to open a db file. 19 20 Return values: 21 22 - None if the database file can't be read; 23 - empty string if the file can be read but can't be recognized 24 - the module name (e.g. "dbm" or "gdbm") if recognized. 25 26 Importing the given module may still fail, and opening the 27 database using that module may still fail. 28 """ 29 30 # Check for dbm first -- this has a .pag and a .dir file 31 try: 32 f = open(filename + os.extsep + "pag", "rb") 33 f.close() 34 # dbm linked with gdbm on OS/2 doesn't have .dir file 35 if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"): 36 f = open(filename + os.extsep + "dir", "rb") 37 f.close() 38 return "dbm" 39 except IOError: 40 # some dbm emulations based on Berkeley DB generate a .db file 41 # some do not, but they should be caught by the dbhash checks 42 try: 43 f = open(filename + os.extsep + "db", "rb") 44 f.close() 45 # guarantee we can actually open the file using dbm 46 # kind of overkill, but since we are dealing with emulations 47 # it seems like a prudent step 48 if dbm is not None: 49 d = dbm.open(filename) 50 d.close() 51 return "dbm" 52 except (IOError, _dbmerror): 53 pass 54 55 # Check for dumbdbm next -- this has a .dir and a .dat file 56 try: 57 # First check for presence of files 58 os.stat(filename + os.extsep + "dat") 59 size = os.stat(filename + os.extsep + "dir").st_size 60 # dumbdbm files with no keys are empty 61 if size == 0: 62 return "dumbdbm" 63 f = open(filename + os.extsep + "dir", "rb") 64 try: 65 if f.read(1) in ("'", '"'): 66 return "dumbdbm" 67 finally: 68 f.close() 69 except (OSError, IOError): 70 pass 71 72 # See if the file exists, return None if not 73 try: 74 f = open(filename, "rb") 75 except IOError: 76 return None 77 78 # Read the start of the file -- the magic number 79 s16 = f.read(16) 80 f.close() 81 s = s16[0:4] 82 83 # Return "" if not at least 4 bytes 84 if len(s) != 4: 85 return "" 86 87 # Convert to 4-byte int in native byte order -- return "" if impossible 88 try: 89 (magic,) = struct.unpack("=l", s) 90 except struct.error: 91 return "" 92 93 # Check for GNU dbm 94 if magic in (0x13579ace, 0x13579acd, 0x13579acf): 95 return "gdbm" 96 97 # Check for old Berkeley db hash file format v2 98 if magic in (0x00061561, 0x61150600): 99 return "bsddb185" 100 101 # Later versions of Berkeley db hash file have a 12-byte pad in 102 # front of the file type 103 try: 104 (magic,) = struct.unpack("=l", s16[-4:]) 105 except struct.error: 106 return "" 107 108 # Check for BSD hash 109 if magic in (0x00061561, 0x61150600): 110 return "dbhash" 111 112 # Unknown 113 return "" 114 115 if __name__ == "__main__": 116 for filename in sys.argv[1:]: 117 print whichdb(filename) or "UNKNOWN", filename 118