|
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 == 0x13579ace: |
|
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 |