blob: ca9c73684f799a4bd78ab818e3dc3ca989283e1b [file] [log] [blame]
Raymond Hettingere54e7262004-10-20 07:17:16 +00001# !/usr/bin/env python
Guido van Rossum8d12a1b1996-07-30 16:30:15 +00002"""Guess which db package to use to open a db file."""
3
Guido van Rossum6252e102007-05-23 20:51:02 +00004import io
Guido van Rossumd74fb6b2001-03-02 06:43:49 +00005import os
Skip Montanaro404378f2002-08-02 17:12:15 +00006import struct
Andrew MacIntyrea1e93e82003-07-11 12:16:48 +00007import sys
Skip Montanaro404378f2002-08-02 17:12:15 +00008
9try:
10 import dbm
11 _dbmerror = dbm.error
12except ImportError:
13 dbm = None
14 # just some sort of valid exception which might be raised in the
15 # dbm test
16 _dbmerror = IOError
Guido van Rossumd74fb6b2001-03-02 06:43:49 +000017
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000018def whichdb(filename):
19 """Guess which db package to use to open a db file.
20
21 Return values:
22
23 - None if the database file can't be read;
24 - empty string if the file can be read but can't be recognized
25 - the module name (e.g. "dbm" or "gdbm") if recognized.
26
27 Importing the given module may still fail, and opening the
28 database using that module may still fail.
29 """
30
31 # Check for dbm first -- this has a .pag and a .dir file
32 try:
Skip Montanaro7a98be22007-08-16 14:35:24 +000033 f = io.open(filename + ".pag", "rb")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000034 f.close()
Andrew MacIntyrea1e93e82003-07-11 12:16:48 +000035 # dbm linked with gdbm on OS/2 doesn't have .dir file
36 if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"):
Skip Montanaro7a98be22007-08-16 14:35:24 +000037 f = io.open(filename + ".dir", "rb")
Andrew MacIntyrea1e93e82003-07-11 12:16:48 +000038 f.close()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000039 return "dbm"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000040 except IOError:
Skip Montanaro404378f2002-08-02 17:12:15 +000041 # some dbm emulations based on Berkeley DB generate a .db file
42 # some do not, but they should be caught by the dbhash checks
43 try:
Skip Montanaro7a98be22007-08-16 14:35:24 +000044 f = io.open(filename + ".db", "rb")
Skip Montanaro404378f2002-08-02 17:12:15 +000045 f.close()
46 # guarantee we can actually open the file using dbm
47 # kind of overkill, but since we are dealing with emulations
48 # it seems like a prudent step
49 if dbm is not None:
50 d = dbm.open(filename)
51 d.close()
52 return "dbm"
53 except (IOError, _dbmerror):
54 pass
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000055
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +000056 # Check for dumbdbm next -- this has a .dir and a .dat file
Thomas Wouters3027b152000-08-04 08:46:59 +000057 try:
Martin v. Löwis17fb5072003-06-14 08:16:34 +000058 # First check for presence of files
Skip Montanaro7a98be22007-08-16 14:35:24 +000059 os.stat(filename + ".dat")
60 size = os.stat(filename + ".dir").st_size
Martin v. Löwis17fb5072003-06-14 08:16:34 +000061 # dumbdbm files with no keys are empty
Martin v. Löwis5b8bfdf2003-06-21 13:54:55 +000062 if size == 0:
Martin v. Löwis17fb5072003-06-14 08:16:34 +000063 return "dumbdbm"
Skip Montanaro7a98be22007-08-16 14:35:24 +000064 f = io.open(filename + ".dir", "rb")
Moshe Zadka7a4409c2000-07-29 05:31:40 +000065 try:
Guido van Rossum6252e102007-05-23 20:51:02 +000066 if f.read(1) in (b"'", b'"'):
Moshe Zadka7a4409c2000-07-29 05:31:40 +000067 return "dumbdbm"
68 finally:
69 f.close()
Martin v. Löwis17fb5072003-06-14 08:16:34 +000070 except (OSError, IOError):
Moshe Zadka7a4409c2000-07-29 05:31:40 +000071 pass
72
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000073 # See if the file exists, return None if not
74 try:
Guido van Rossum6252e102007-05-23 20:51:02 +000075 f = io.open(filename, "rb")
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000076 except IOError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000077 return None
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000078
Guido van Rossumcf09a391999-06-08 13:13:16 +000079 # Read the start of the file -- the magic number
80 s16 = f.read(16)
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000081 f.close()
Guido van Rossumcf09a391999-06-08 13:13:16 +000082 s = s16[0:4]
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000083
84 # Return "" if not at least 4 bytes
85 if len(s) != 4:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000086 return ""
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000087
88 # Convert to 4-byte int in native byte order -- return "" if impossible
89 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 (magic,) = struct.unpack("=l", s)
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000091 except struct.error:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000092 return ""
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000093
94 # Check for GNU dbm
95 if magic == 0x13579ace:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000096 return "gdbm"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000097
Skip Montanaro02cd3652003-05-06 20:42:10 +000098 # Check for old Berkeley db hash file format v2
Guido van Rossumb86ba121998-04-28 15:41:03 +000099 if magic in (0x00061561, 0x61150600):
Skip Montanaro02cd3652003-05-06 20:42:10 +0000100 return "bsddb185"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +0000101
Skip Montanaro02cd3652003-05-06 20:42:10 +0000102 # Later versions of Berkeley db hash file have a 12-byte pad in
103 # front of the file type
Guido van Rossumcf09a391999-06-08 13:13:16 +0000104 try:
Fred Drake13a2c272000-02-10 17:17:14 +0000105 (magic,) = struct.unpack("=l", s16[-4:])
Guido van Rossumcf09a391999-06-08 13:13:16 +0000106 except struct.error:
107 return ""
108
109 # Check for BSD hash
110 if magic in (0x00061561, 0x61150600):
111 return "dbhash"
112
Guido van Rossum8d12a1b1996-07-30 16:30:15 +0000113 # Unknown
114 return ""
Raymond Hettingere54e7262004-10-20 07:17:16 +0000115
116if __name__ == "__main__":
117 for filename in sys.argv[1:]:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000118 print(whichdb(filename) or "UNKNOWN", filename)