]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/python/whichdb.py
dist/mkfile: run binds in subshell
[plan9front.git] / sys / lib / python / whichdb.py
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