whichdb.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # !/usr/bin/env python
  2. """Guess which db package to use to open a db file."""
  3. import os
  4. import struct
  5. import sys
  6. try:
  7. import dbm
  8. _dbmerror = dbm.error
  9. except ImportError:
  10. dbm = None
  11. # just some sort of valid exception which might be raised in the
  12. # dbm test
  13. _dbmerror = IOError
  14. def whichdb(filename):
  15. """Guess which db package to use to open a db file.
  16. Return values:
  17. - None if the database file can't be read;
  18. - empty string if the file can be read but can't be recognized
  19. - the module name (e.g. "dbm" or "gdbm") if recognized.
  20. Importing the given module may still fail, and opening the
  21. database using that module may still fail.
  22. """
  23. # Check for dbm first -- this has a .pag and a .dir file
  24. try:
  25. f = open(filename + os.extsep + "pag", "rb")
  26. f.close()
  27. # dbm linked with gdbm on OS/2 doesn't have .dir file
  28. if not (dbm.library == "GNU gdbm" and sys.platform == "os2emx"):
  29. f = open(filename + os.extsep + "dir", "rb")
  30. f.close()
  31. return "dbm"
  32. except IOError:
  33. # some dbm emulations based on Berkeley DB generate a .db file
  34. # some do not, but they should be caught by the dbhash checks
  35. try:
  36. f = open(filename + os.extsep + "db", "rb")
  37. f.close()
  38. # guarantee we can actually open the file using dbm
  39. # kind of overkill, but since we are dealing with emulations
  40. # it seems like a prudent step
  41. if dbm is not None:
  42. d = dbm.open(filename)
  43. d.close()
  44. return "dbm"
  45. except (IOError, _dbmerror):
  46. pass
  47. # Check for dumbdbm next -- this has a .dir and a .dat file
  48. try:
  49. # First check for presence of files
  50. os.stat(filename + os.extsep + "dat")
  51. size = os.stat(filename + os.extsep + "dir").st_size
  52. # dumbdbm files with no keys are empty
  53. if size == 0:
  54. return "dumbdbm"
  55. f = open(filename + os.extsep + "dir", "rb")
  56. try:
  57. if f.read(1) in ["'", '"']:
  58. return "dumbdbm"
  59. finally:
  60. f.close()
  61. except (OSError, IOError):
  62. pass
  63. # See if the file exists, return None if not
  64. try:
  65. f = open(filename, "rb")
  66. except IOError:
  67. return None
  68. # Read the start of the file -- the magic number
  69. s16 = f.read(16)
  70. f.close()
  71. s = s16[0:4]
  72. # Return "" if not at least 4 bytes
  73. if len(s) != 4:
  74. return ""
  75. # Convert to 4-byte int in native byte order -- return "" if impossible
  76. try:
  77. (magic,) = struct.unpack("=l", s)
  78. except struct.error:
  79. return ""
  80. # Check for GNU dbm
  81. if magic == 0x13579ace:
  82. return "gdbm"
  83. # Check for old Berkeley db hash file format v2
  84. if magic in (0x00061561, 0x61150600):
  85. return "bsddb185"
  86. # Later versions of Berkeley db hash file have a 12-byte pad in
  87. # front of the file type
  88. try:
  89. (magic,) = struct.unpack("=l", s16[-4:])
  90. except struct.error:
  91. return ""
  92. # Check for BSD hash
  93. if magic in (0x00061561, 0x61150600):
  94. return "dbhash"
  95. # Unknown
  96. return ""
  97. if __name__ == "__main__":
  98. for filename in sys.argv[1:]:
  99. print whichdb(filename) or "UNKNOWN", filename