Home | History | Annotate | Download | only in python2.7
      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