#! @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()