#! @PYTHON@ # # Copyright (C) 1998-2018 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """Check a list's config database file for integrity. All of the following files are checked: config.pck config.pck.last config.db config.db.last config.safety It's okay if any of these are missing. config.pck and config.pck.last are pickled versions of the config database file for 2.1a3 and beyond. config.db and config.db.last are used in all earlier versions, and these are Python marshals. config.safety is a pickle written by 2.1a3 and beyond when the primary config.pck file could not be read. Usage: %(PROGRAM)s [options] [listname [listname ...]] Options: --all / -a Check the databases for all lists. Otherwise only the lists named on the command line are checked. --verbose / -v Verbose output. The state of every tested file is printed. Otherwise only corrupt files are displayed. --help / -h Print this text and exit. """ import sys import os import errno import getopt import marshal import cPickle import paths from Mailman import mm_cfg from Mailman import Utils from Mailman.MailList import MailList from Mailman.i18n import C_ PROGRAM = sys.argv[0] def usage(code, msg=''): if code: fd = sys.stderr else: fd = sys.stdout print >> fd, C_(__doc__) if msg: print >> fd, msg sys.exit(code) def testfile(dbfile): if dbfile.endswith('.db') or dbfile.endswith('.db.last'): loadfunc = marshal.load elif dbfile.endswith('.pck') or dbfile.endswith('.pck.last'): loadfunc = cPickle.load else: assert 0 fp = open(dbfile) try: loadfunc(fp) finally: fp.close() def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'ahv', ['all', 'verbose', 'help']) except getopt.error, msg: usage(1, msg) verbose = 0 listnames = args for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-v', '--verbose'): verbose = 1 elif opt in ('-a', '--all'): listnames = Utils.list_names() listnames = [n.lower().strip() for n in listnames] if not listnames: print C_('Nothing to do.') sys.exit(0) for listname in listnames: if not Utils.list_exists(listname): print C_('No list named:'), listname continue mlist = MailList(listname, lock=0) pfile = os.path.join(mlist.fullpath(), 'config.pck') plast = pfile + '.last' dfile = os.path.join(mlist.fullpath(), 'config.db') dlast = dfile + '.last' if verbose: print C_('List:'), listname for file in (pfile, plast, dfile, dlast): status = 0 try: testfile(file) except IOError, e: # Don't report ENOENT unless we're in verbose mode if verbose or e.errno <> errno.ENOENT: status = e except Exception, e: status = e # Report errors if status: if isinstance(status, EnvironmentError): # This already includes the file name print ' ', status else: print ' %s: %s' % (file, status) elif verbose: print C_(' %(file)s: okay') if __name__ == '__main__': main()