| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 1 | """Guess which db package to use to open a db file.""" | 
 | 2 |  | 
| Guido van Rossum | d74fb6b | 2001-03-02 06:43:49 +0000 | [diff] [blame] | 3 | import os | 
| Skip Montanaro | 404378f | 2002-08-02 17:12:15 +0000 | [diff] [blame] | 4 | import struct | 
| Andrew MacIntyre | a1e93e8 | 2003-07-11 12:16:48 +0000 | [diff] [blame] | 5 | import sys | 
| Skip Montanaro | 404378f | 2002-08-02 17:12:15 +0000 | [diff] [blame] | 6 |  | 
 | 7 | try: | 
 | 8 |     import dbm | 
 | 9 |     _dbmerror = dbm.error | 
 | 10 | except ImportError: | 
 | 11 |     dbm = None | 
 | 12 |     # just some sort of valid exception which might be raised in the | 
 | 13 |     # dbm test | 
 | 14 |     _dbmerror = IOError | 
| Guido van Rossum | d74fb6b | 2001-03-02 06:43:49 +0000 | [diff] [blame] | 15 |  | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 16 | def whichdb(filename): | 
 | 17 |     """Guess which db package to use to open a db file. | 
 | 18 |  | 
 | 19 |     Return values: | 
 | 20 |  | 
 | 21 |     - None if the database file can't be read; | 
 | 22 |     - empty string if the file can be read but can't be recognized | 
 | 23 |     - the module name (e.g. "dbm" or "gdbm") if recognized. | 
 | 24 |  | 
 | 25 |     Importing the given module may still fail, and opening the | 
 | 26 |     database using that module may still fail. | 
 | 27 |     """ | 
 | 28 |  | 
 | 29 |     # Check for dbm first -- this has a .pag and a .dir file | 
 | 30 |     try: | 
| Guido van Rossum | e2ae77b | 2001-10-24 20:42:55 +0000 | [diff] [blame] | 31 |         f = open(filename + os.extsep + "pag", "rb") | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 32 |         f.close() | 
| Andrew MacIntyre | a1e93e8 | 2003-07-11 12:16:48 +0000 | [diff] [blame] | 33 |         # dbm linked with gdbm on OS/2 doesn't have .dir file | 
 | 34 |         if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"): | 
 | 35 |             f = open(filename + os.extsep + "dir", "rb") | 
 | 36 |             f.close() | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 37 |         return "dbm" | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 38 |     except IOError: | 
| Skip Montanaro | 404378f | 2002-08-02 17:12:15 +0000 | [diff] [blame] | 39 |         # some dbm emulations based on Berkeley DB generate a .db file | 
 | 40 |         # some do not, but they should be caught by the dbhash checks | 
 | 41 |         try: | 
 | 42 |             f = open(filename + os.extsep + "db", "rb") | 
 | 43 |             f.close() | 
 | 44 |             # guarantee we can actually open the file using dbm | 
 | 45 |             # kind of overkill, but since we are dealing with emulations | 
 | 46 |             # it seems like a prudent step | 
 | 47 |             if dbm is not None: | 
 | 48 |                 d = dbm.open(filename) | 
 | 49 |                 d.close() | 
 | 50 |                 return "dbm" | 
 | 51 |         except (IOError, _dbmerror): | 
 | 52 |             pass | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 53 |  | 
| Walter Dörwald | f0dfc7a | 2003-10-20 14:01:56 +0000 | [diff] [blame] | 54 |     # Check for dumbdbm next -- this has a .dir and a .dat file | 
| Thomas Wouters | 3027b15 | 2000-08-04 08:46:59 +0000 | [diff] [blame] | 55 |     try: | 
| Martin v. Löwis | 17fb507 | 2003-06-14 08:16:34 +0000 | [diff] [blame] | 56 |         # First check for presence of files | 
| Martin v. Löwis | 5b8bfdf | 2003-06-21 13:54:55 +0000 | [diff] [blame] | 57 |         os.stat(filename + os.extsep + "dat") | 
 | 58 |         size = os.stat(filename + os.extsep + "dir").st_size | 
| Martin v. Löwis | 17fb507 | 2003-06-14 08:16:34 +0000 | [diff] [blame] | 59 |         # dumbdbm files with no keys are empty | 
| Martin v. Löwis | 5b8bfdf | 2003-06-21 13:54:55 +0000 | [diff] [blame] | 60 |         if size == 0: | 
| Martin v. Löwis | 17fb507 | 2003-06-14 08:16:34 +0000 | [diff] [blame] | 61 |             return "dumbdbm" | 
| Guido van Rossum | e2ae77b | 2001-10-24 20:42:55 +0000 | [diff] [blame] | 62 |         f = open(filename + os.extsep + "dir", "rb") | 
| Moshe Zadka | 7a4409c | 2000-07-29 05:31:40 +0000 | [diff] [blame] | 63 |         try: | 
 | 64 |             if f.read(1) in ["'", '"']: | 
 | 65 |                 return "dumbdbm" | 
 | 66 |         finally: | 
 | 67 |             f.close() | 
| Martin v. Löwis | 17fb507 | 2003-06-14 08:16:34 +0000 | [diff] [blame] | 68 |     except (OSError, IOError): | 
| Moshe Zadka | 7a4409c | 2000-07-29 05:31:40 +0000 | [diff] [blame] | 69 |         pass | 
 | 70 |  | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 71 |     # See if the file exists, return None if not | 
 | 72 |     try: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 73 |         f = open(filename, "rb") | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 74 |     except IOError: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 75 |         return None | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 76 |  | 
| Guido van Rossum | cf09a39 | 1999-06-08 13:13:16 +0000 | [diff] [blame] | 77 |     # Read the start of the file -- the magic number | 
 | 78 |     s16 = f.read(16) | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 79 |     f.close() | 
| Guido van Rossum | cf09a39 | 1999-06-08 13:13:16 +0000 | [diff] [blame] | 80 |     s = s16[0:4] | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 81 |  | 
 | 82 |     # Return "" if not at least 4 bytes | 
 | 83 |     if len(s) != 4: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 84 |         return "" | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 85 |  | 
 | 86 |     # Convert to 4-byte int in native byte order -- return "" if impossible | 
 | 87 |     try: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 88 |         (magic,) = struct.unpack("=l", s) | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 89 |     except struct.error: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 90 |         return "" | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 91 |  | 
 | 92 |     # Check for GNU dbm | 
 | 93 |     if magic == 0x13579ace: | 
| Guido van Rossum | 45e2fbc | 1998-03-26 21:13:24 +0000 | [diff] [blame] | 94 |         return "gdbm" | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 95 |  | 
| Skip Montanaro | 02cd365 | 2003-05-06 20:42:10 +0000 | [diff] [blame] | 96 |     # Check for old Berkeley db hash file format v2 | 
| Guido van Rossum | b86ba12 | 1998-04-28 15:41:03 +0000 | [diff] [blame] | 97 |     if magic in (0x00061561, 0x61150600): | 
| Skip Montanaro | 02cd365 | 2003-05-06 20:42:10 +0000 | [diff] [blame] | 98 |         return "bsddb185" | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 99 |  | 
| Skip Montanaro | 02cd365 | 2003-05-06 20:42:10 +0000 | [diff] [blame] | 100 |     # Later versions of Berkeley db hash file have a 12-byte pad in | 
 | 101 |     # front of the file type | 
| Guido van Rossum | cf09a39 | 1999-06-08 13:13:16 +0000 | [diff] [blame] | 102 |     try: | 
| Fred Drake | 13a2c27 | 2000-02-10 17:17:14 +0000 | [diff] [blame] | 103 |         (magic,) = struct.unpack("=l", s16[-4:]) | 
| Guido van Rossum | cf09a39 | 1999-06-08 13:13:16 +0000 | [diff] [blame] | 104 |     except struct.error: | 
 | 105 |         return "" | 
 | 106 |  | 
 | 107 |     # Check for BSD hash | 
 | 108 |     if magic in (0x00061561, 0x61150600): | 
 | 109 |         return "dbhash" | 
 | 110 |  | 
| Guido van Rossum | 8d12a1b | 1996-07-30 16:30:15 +0000 | [diff] [blame] | 111 |     # Unknown | 
 | 112 |     return "" |