blob: f077f875310eeeacb0ff844c186db21baf36874c [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 Rossumd74fb6b2001-03-02 06:43:49 +00004import os
Skip Montanaro404378f2002-08-02 17:12:15 +00005import struct
Andrew MacIntyrea1e93e82003-07-11 12:16:48 +00006import sys
Skip Montanaro404378f2002-08-02 17:12:15 +00007
8try:
9 import dbm
10 _dbmerror = dbm.error
11except ImportError:
12 dbm = None
13 # just some sort of valid exception which might be raised in the
14 # dbm test
15 _dbmerror = IOError
Guido van Rossumd74fb6b2001-03-02 06:43:49 +000016
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000017def 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:
Guido van Rossume2ae77b2001-10-24 20:42:55 +000032 f = open(filename + os.extsep + "pag", "rb")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000033 f.close()
Andrew MacIntyrea1e93e82003-07-11 12:16:48 +000034 # 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()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000038 return "dbm"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000039 except IOError:
Skip Montanaro404378f2002-08-02 17:12:15 +000040 # 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
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000054
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +000055 # Check for dumbdbm next -- this has a .dir and a .dat file
Thomas Wouters3027b152000-08-04 08:46:59 +000056 try:
Martin v. Löwis17fb5072003-06-14 08:16:34 +000057 # First check for presence of files
Martin v. Löwis5b8bfdf2003-06-21 13:54:55 +000058 os.stat(filename + os.extsep + "dat")
59 size = os.stat(filename + os.extsep + "dir").st_size
Martin v. Löwis17fb5072003-06-14 08:16:34 +000060 # dumbdbm files with no keys are empty
Martin v. Löwis5b8bfdf2003-06-21 13:54:55 +000061 if size == 0:
Martin v. Löwis17fb5072003-06-14 08:16:34 +000062 return "dumbdbm"
Guido van Rossume2ae77b2001-10-24 20:42:55 +000063 f = open(filename + os.extsep + "dir", "rb")
Moshe Zadka7a4409c2000-07-29 05:31:40 +000064 try:
Raymond Hettingerdbecd932005-02-06 06:57:08 +000065 if f.read(1) in ("'", '"'):
Moshe Zadka7a4409c2000-07-29 05:31:40 +000066 return "dumbdbm"
67 finally:
68 f.close()
Martin v. Löwis17fb5072003-06-14 08:16:34 +000069 except (OSError, IOError):
Moshe Zadka7a4409c2000-07-29 05:31:40 +000070 pass
71
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000072 # See if the file exists, return None if not
73 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000074 f = open(filename, "rb")
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000075 except IOError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000076 return None
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000077
Guido van Rossumcf09a391999-06-08 13:13:16 +000078 # Read the start of the file -- the magic number
79 s16 = f.read(16)
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000080 f.close()
Guido van Rossumcf09a391999-06-08 13:13:16 +000081 s = s16[0:4]
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000082
83 # Return "" if not at least 4 bytes
84 if len(s) != 4:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000085 return ""
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000086
87 # Convert to 4-byte int in native byte order -- return "" if impossible
88 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000089 (magic,) = struct.unpack("=l", s)
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000090 except struct.error:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 return ""
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000092
93 # Check for GNU dbm
94 if magic == 0x13579ace:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 return "gdbm"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +000096
Skip Montanaro02cd3652003-05-06 20:42:10 +000097 # Check for old Berkeley db hash file format v2
Guido van Rossumb86ba121998-04-28 15:41:03 +000098 if magic in (0x00061561, 0x61150600):
Skip Montanaro02cd3652003-05-06 20:42:10 +000099 return "bsddb185"
Guido van Rossum8d12a1b1996-07-30 16:30:15 +0000100
Skip Montanaro02cd3652003-05-06 20:42:10 +0000101 # Later versions of Berkeley db hash file have a 12-byte pad in
102 # front of the file type
Guido van Rossumcf09a391999-06-08 13:13:16 +0000103 try:
Fred Drake13a2c272000-02-10 17:17:14 +0000104 (magic,) = struct.unpack("=l", s16[-4:])
Guido van Rossumcf09a391999-06-08 13:13:16 +0000105 except struct.error:
106 return ""
107
108 # Check for BSD hash
109 if magic in (0x00061561, 0x61150600):
110 return "dbhash"
111
Guido van Rossum8d12a1b1996-07-30 16:30:15 +0000112 # Unknown
113 return ""
Raymond Hettingere54e7262004-10-20 07:17:16 +0000114
115if __name__ == "__main__":
116 for filename in sys.argv[1:]:
117 print whichdb(filename) or "UNKNOWN", filename