1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
"""Guess which db package to use to open a db file."""
import struct
def whichdb(filename):
"""Guess which db package to use to open a db file.
Return values:
- None if the database file can't be read;
- empty string if the file can be read but can't be recognized
- the module name (e.g. "dbm" or "gdbm") if recognized.
Importing the given module may still fail, and opening the
database using that module may still fail.
"""
# Check for dbm first -- this has a .pag and a .dir file
try:
f = open(filename + ".pag", "rb")
f.close()
f = open(filename + ".dir", "rb")
f.close()
return "dbm"
except IOError:
pass
# Then, check for dumbdbm -- this has a .dat and a .dir file
try:
f = open(filename + ".dat", "rb")
f.close()
f = open(filename + ".dir", "rb")
f.close()
return "dumbdbm"
except IOError:
pass
# See if the file exists, return None if not
try:
f = open(filename, "rb")
except IOError:
return None
# Read the first 4 bytes of the file -- the magic number
s = f.read(4)
f.close()
# Return "" if not at least 4 bytes
if len(s) != 4:
return ""
# Convert to 4-byte int in native byte order -- return "" if impossible
try:
(magic,) = struct.unpack("=l", s)
except struct.error:
return ""
# Check for GNU dbm
if magic == 0x13579ace:
return "gdbm"
#
# Debian: This is a new feature not yet seen in the upstream code:
# We will also support DB 2 Hash files. They're identified with
# the dbhash/bsddb module, while old DB 1.85 Hash files are
# identified with the legacy db1hash/bsddb1 module (which is
# indeed the same as dbhash/bsddb, but linked with a legacy
# libdb1 library).
#
# To detect DB 2 Hash files, we have to use the magic number at
# position 12.
#
# Check for BSD hash
if magic in (0x00061561, 0x61150600):
return "db1hash"
# See if the file exists, return None if not
try:
f = open(filename, "rb")
except IOError:
return None
# Read the first 16 bytes of the file -- the magic number
s = f.read(16)
f.close()
# Return "" if not at least 16 bytes
if len(s) != 16:
return ""
try:
(magic,) = struct.unpack("=l", s[12:])
except struct.error:
return ""
# Check for BSD DB 2 hash
if magic in (0x00061561, 0x61150600):
return "dbhash"
# Unknown
return ""
|