better permission handling of startup script
minor bugfixes update of CryptoBoxWebserver manpage
This commit is contained in:
parent
949f78958b
commit
9ec9475015
13 changed files with 200 additions and 87 deletions
|
@ -50,7 +50,7 @@ allowedProgs = {
|
|||
|
||||
## this line is necessary to run unittests - otherwise these tests are too strict
|
||||
# TODO: check this before every release!
|
||||
OVERRIDE_FILECHECK = True
|
||||
OVERRIDE_FILECHECK = False
|
||||
|
||||
DEV_TYPES = { "pipe":1, "char":2, "dir":4, "block":6, "file":8, "link":10, "socket":12}
|
||||
EVENT_MARKER = '_event_scripts_'
|
||||
|
|
|
@ -67,7 +67,7 @@ except:
|
|||
SERVER_ENVIRONMENT = "production"
|
||||
|
||||
class CryptoBoxWebserver:
|
||||
'''this class starts the cherryp webserver and serves the single sites'''
|
||||
'''this class starts the cherrypy webserver and serves the single sites'''
|
||||
|
||||
def __init__(self, opts):
|
||||
self.opts = opts
|
||||
|
@ -77,20 +77,27 @@ class CryptoBoxWebserver:
|
|||
sys.exit(1)
|
||||
## store the absolute path as we will chdir later (for daemons)
|
||||
self.conffile = os.path.realpath(opts.conffile)
|
||||
## drop privileges to run the cryptobox without root permissions
|
||||
self.drop_privileges_temporarily()
|
||||
## initialize site class
|
||||
try:
|
||||
cherrypy.root = cryptobox.web.sites.WebInterfaceSites(self.conffile)
|
||||
except (CBConfigError,CBEnvironmentError), errMsg:
|
||||
self.website = cherrypy.root
|
||||
except (CBConfigError,CBEnvironmentError), err_msg:
|
||||
sys.stderr.write("Error: the CryptoBox is misconfigured - please fix it!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.stderr.write("%s\n" % str(err_msg))
|
||||
sys.exit(1)
|
||||
## restore privileges, as we need them to connect to a low socket (<1024)
|
||||
self.restore_privileges()
|
||||
## expose static content and set options
|
||||
## beware:
|
||||
cherrypy.config.update({
|
||||
"global": {
|
||||
"server.socket_port" : int(opts.port),
|
||||
"server.socket_host" : opts.host,
|
||||
"server.log_to_screen" : not opts.background and opts.verbose,
|
||||
"server.log_tracebacks" : opts.verbose,
|
||||
"server.log_request_headers": opts.verbose,
|
||||
"server.environment": SERVER_ENVIRONMENT,
|
||||
"server.log_file" : opts.logfile },
|
||||
"/cryptobox-misc": {
|
||||
|
@ -101,49 +108,102 @@ class CryptoBoxWebserver:
|
|||
"staticFilter.file": os.path.realpath(os.path.join(opts.datadir, 'favicon.ico'))}
|
||||
|
||||
})
|
||||
self.define_exit_handlers(cherrypy.root)
|
||||
|
||||
|
||||
def define_exit_handlers(self, cbw):
|
||||
import atexit
|
||||
import signal
|
||||
## define exit handler for normal termination (via sys.exit)
|
||||
def exit_handler():
|
||||
cbw.cleanup()
|
||||
try:
|
||||
os.remove(self.opts.pidfile)
|
||||
except OSError:
|
||||
pass
|
||||
atexit.register(exit_handler)
|
||||
## catch kill signal
|
||||
def kill_signal_handler(signum, frame):
|
||||
cbw.cbox.log.info("Kill signal handler called: %d" % signum)
|
||||
sys.exit(1)
|
||||
signal.signal(signal.SIGTERM, kill_signal_handler)
|
||||
def get_user_info(self):
|
||||
"""Retrieve the uid, gid and additional groups of the given user
|
||||
"""
|
||||
import pwd, grp
|
||||
user_entry = pwd.getpwuid(self.opts.user)
|
||||
## get the new uid and gid
|
||||
pw_uid, pw_gid = user_entry[2], user_entry[3]
|
||||
## change the owner of the webserver log file
|
||||
try:
|
||||
os.chown(self.opts.logfile, pw_uid, pw_gid)
|
||||
except OSError:
|
||||
## fail silently
|
||||
pass
|
||||
## calculate additional groups of the given user
|
||||
additional_groups = [ entry[2]
|
||||
for entry in grp.getgrall()
|
||||
if pw_uid in entry[3] ]
|
||||
return (pw_uid, pw_gid, additional_groups)
|
||||
|
||||
|
||||
def drop_privileges_temporarily(self):
|
||||
"""Temporarily drop privileges.
|
||||
"""
|
||||
if self.opts.user is None:
|
||||
return
|
||||
(pw_uid, pw_gid, additional_groups) = self.get_user_info()
|
||||
try:
|
||||
os.setegid(pw_gid)
|
||||
os.seteuid(pw_uid)
|
||||
except OSError, err_msg:
|
||||
sys.stderr.write("Failed to drop privileges temporarily: %s\n" % err_msg)
|
||||
|
||||
|
||||
def restore_privileges(self):
|
||||
"""Restore previously temporarily dropped privileges.
|
||||
"""
|
||||
if self.opts.user is None:
|
||||
return
|
||||
try:
|
||||
os.setegid(os.getgid())
|
||||
os.seteuid(os.getuid())
|
||||
except OSError, err_msg:
|
||||
sys.stderr.write("Failed to restore privileges: %s\n" % err_msg)
|
||||
|
||||
|
||||
def drop_privileges_permanently(self):
|
||||
"""Drop all privileges of the current process and acquire the privileges of the
|
||||
given user instead.
|
||||
"""
|
||||
if self.opts.user is None:
|
||||
return
|
||||
(pw_uid, pw_gid, additional_groups) = self.get_user_info()
|
||||
try:
|
||||
os.setgroups(additional_groups)
|
||||
os.setregid(pw_gid, pw_gid)
|
||||
os.setreuid(pw_uid, pw_uid)
|
||||
except OSError, err_msg:
|
||||
sys.stderr.write("Failed to drop privileges permanently: %s\n" % err_msg)
|
||||
|
||||
|
||||
|
||||
def start(self):
|
||||
cherrypy.server.start()
|
||||
try:
|
||||
cherrypy.server.start(initOnly=True)
|
||||
self.drop_privileges_permanently()
|
||||
cherrypy.server.wait_for_http_ready()
|
||||
except cherrypy._cperror.NotReady, err_msg:
|
||||
sys.stderr.write("Failed to start CryptoBox: %s\n" % err_msg)
|
||||
sys.exit(1)
|
||||
except Exception, err_msg:
|
||||
if err_msg == "(98, 'Address already in use')":
|
||||
sys.stderr.write("Failed to start CryptoBox: %s\n" % err_msg)
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
|
||||
|
||||
def fork_to_background():
|
||||
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
||||
## check the original for exhaustive comments
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
except OSError, err_msg:
|
||||
sys.stderr.write("Error: failed to fork cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.stderr.write("%s\n" % err_msg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the first child
|
||||
os.setsid()
|
||||
try:
|
||||
pid = os.fork()
|
||||
except OSError, errMsg:
|
||||
except OSError, err_msg:
|
||||
sys.stderr.write("Error: failed to fork second cryptobox daemon process!\n")
|
||||
sys.stderr.write("%s\n" % errMsg)
|
||||
sys.stderr.write("%s\n" % err_msg)
|
||||
sys.exit(1)
|
||||
if pid == 0: # the second child
|
||||
## we do not change the directory - otherwise there seems to be a race condition with the python interpreter loading this script file
|
||||
|
@ -163,16 +223,17 @@ def close_open_files():
|
|||
## use the following lines to close all open files (including the log file)
|
||||
# maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
||||
# if (maxfd == resource.RLIM_INFINITY):
|
||||
# maxfd = 1024
|
||||
# maxfd = 1024
|
||||
maxfd = 2
|
||||
for fd in range(0, maxfd):
|
||||
try:
|
||||
os.close(fd)
|
||||
## close all except for stderr - we will redirect it later
|
||||
if fd != 2:
|
||||
os.close(fd)
|
||||
except OSError: # ERROR, fd wasn't open to begin with (ignored)
|
||||
pass
|
||||
os.open(os.devnull, os.O_RDWR) # standard input (0)
|
||||
os.dup2(0, 1) # standard output (1)
|
||||
os.dup2(0, 2) # standard error (2)
|
||||
|
||||
|
||||
def write_pid_file(pid_file):
|
||||
|
@ -183,14 +244,15 @@ def write_pid_file(pid_file):
|
|||
pidf = open(pid_file,"w")
|
||||
pidf.write(str(os.getpid()))
|
||||
pidf.close()
|
||||
except (IOError, OSError), errMsg:
|
||||
except (IOError, OSError), err_msg:
|
||||
sys.stderr.write(
|
||||
"Warning: failed to write pid file (%s): %s\n" % (pid_file, errMsg))
|
||||
"Warning: failed to write pid file (%s): %s\n" % (pid_file, err_msg))
|
||||
## it is just a warning - no need to break
|
||||
|
||||
|
||||
def parseOptions():
|
||||
import cryptobox
|
||||
import pwd
|
||||
version = "%prog" + cryptobox.__version__
|
||||
parser = OptionParser(version=version)
|
||||
parser.set_defaults(conffile="/etc/cryptobox-server/cryptobox.conf",
|
||||
|
@ -200,7 +262,8 @@ def parseOptions():
|
|||
logfile="/var/log/cryptobox-server/webserver.log",
|
||||
port="8080",
|
||||
host="",
|
||||
verbose=True)
|
||||
verbose=True,
|
||||
user=None)
|
||||
parser.add_option("-c", "--config", dest="conffile",
|
||||
help="read configuration from FILE", metavar="FILE")
|
||||
parser.add_option("","--pidfile", dest="pidfile",
|
||||
|
@ -217,6 +280,8 @@ def parseOptions():
|
|||
help="write webserver log to FILE")
|
||||
parser.add_option("","--host", dest="host", metavar="HOST",
|
||||
help="attach to HOST")
|
||||
parser.add_option("-u","--user", dest="user", metavar="USER",
|
||||
help="change to USER after starting the webserver")
|
||||
(options, args) = parser.parse_args()
|
||||
## we do not expect any remaining arguments
|
||||
if len(args) != 0:
|
||||
|
@ -232,29 +297,66 @@ def parseOptions():
|
|||
parser.error("invalid port number: %s" % str(options.port))
|
||||
except ValueError:
|
||||
parser.error("invalid port specified (%s) - it must be a number" % (options.port))
|
||||
if options.user:
|
||||
try:
|
||||
try:
|
||||
## check for the user given as uid
|
||||
uid = pwd.getpwuid(int(options.user))[2]
|
||||
except ValueError:
|
||||
## check for the user given as name
|
||||
uid = pwd.getpwnam(options.user)[2]
|
||||
except KeyError:
|
||||
## invalid user specified
|
||||
parser.error("invalid user specified (%s)" % options.user)
|
||||
## we will use the uid
|
||||
options.user = uid
|
||||
return options
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
## process arguments
|
||||
options = parseOptions()
|
||||
## set umask to 022 (aka 755) - octal value
|
||||
os.umask(022)
|
||||
## run the webserver as a daemon process
|
||||
if options.background: fork_to_background()
|
||||
## write pid file
|
||||
write_pid_file(options.pidfile)
|
||||
## initialize the webserver class (before forking to get some error messages)
|
||||
cbw = CryptoBoxWebserver(options)
|
||||
## close open files to allow background execution
|
||||
if options.background: close_open_files()
|
||||
## fork to background before cbw.start() - otherwise we lose the socket
|
||||
if options.background:
|
||||
fork_to_background()
|
||||
## start the webserver
|
||||
try:
|
||||
cbw.start()
|
||||
except CBError, errMsg:
|
||||
except CBError, err_msg:
|
||||
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
|
||||
sys.stderr.write("%s\n" % str(errMsg))
|
||||
sys.stderr.write("%s\n" % str(err_msg))
|
||||
sys.stderr.write("Check the log file for details.\n")
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
## redirect stderr to the webserver's logfile
|
||||
if options.background:
|
||||
## replace stdin and stdout by /dev/null
|
||||
close_open_files()
|
||||
## replace stderr by the webserver logfile
|
||||
os.close(2)
|
||||
os.open(options.logfile, os.O_APPEND)
|
||||
## startup went fine - fork is done - now we may write the pid file
|
||||
## write pid file
|
||||
write_pid_file(options.pidfile)
|
||||
def exit_handler(signum, sigframe):
|
||||
cbw.website.cbox.log.info("Shutting down ...")
|
||||
cbw.website.cleanup()
|
||||
try:
|
||||
os.remove(options.pidfile)
|
||||
except OSError:
|
||||
pass
|
||||
os._exit(0)
|
||||
## the signal handler gets called by a kill signal (usually in background mode)
|
||||
import signal
|
||||
signal.signal(signal.SIGTERM, exit_handler)
|
||||
## this exit handler gets called by KeyboardInterrupt and similar ones (foreground)
|
||||
import atexit
|
||||
atexit.register(exit_handler, None, None)
|
||||
## this will never exit - one of the above exit handlers will get triggered
|
||||
cherrypy.server.block()
|
||||
|
||||
|
|
4
debian/changelog
vendored
4
debian/changelog
vendored
|
@ -1,8 +1,8 @@
|
|||
cryptobox (0.3.0.1-1) unstable; urgency=low
|
||||
cryptobox (0.3.1-1) unstable; urgency=low
|
||||
|
||||
* new upstream release
|
||||
|
||||
-- Lars Kruse <devel@sumpfralle.de> Mon, 18 Dec 2006 09:07:32 +0100
|
||||
-- Lars Kruse <devel@sumpfralle.de> Tue, 19 Dec 2006 12:34:57 +0100
|
||||
|
||||
cryptobox (0.3.0-1) unstable; urgency=low
|
||||
|
||||
|
|
1
debian/cryptobox-server.default
vendored
1
debian/cryptobox-server.default
vendored
|
@ -9,7 +9,6 @@ NO_START=1
|
|||
RUNAS=cryptobox
|
||||
|
||||
# listening port
|
||||
# for now please use a port above 1024
|
||||
PORT=8080
|
||||
|
||||
# some more server options (rarely necessary)
|
||||
|
|
8
debian/cryptobox-server.init
vendored
8
debian/cryptobox-server.init
vendored
|
@ -37,7 +37,7 @@ test -x "$DAEMON" || DAEMON=/usr/bin/CryptoBoxWebserver
|
|||
PYTHON_EXEC=/usr/bin/python
|
||||
PIDFILE=/var/run/cryptobox-server/webserver.pid
|
||||
DESC="CryptoBox Daemon (webinterface)"
|
||||
OPTIONS="-B --pidfile=$PIDFILE --config=$CONF_FILE --logfile=$LOGFILE --host=$HOST --port=$PORT $SERVER_OPTS"
|
||||
OPTIONS="-B --pidfile=$PIDFILE --config=$CONF_FILE --logfile=$LOGFILE --host=$HOST --port=$PORT --user=$RUNAS $SERVER_OPTS"
|
||||
|
||||
# check if the package is installed
|
||||
test -e "$DAEMON" || exit 0
|
||||
|
@ -51,13 +51,13 @@ case "$1" in
|
|||
PIDDIR=$(dirname "$PIDFILE")
|
||||
if [ -d "$PIDDIR" ]
|
||||
then mkdir -p "$PIDDIR"
|
||||
# necessary: the cryptobox server needs the permission to remove the pid file
|
||||
chown $RUNAS:root "$PIDDIR"
|
||||
chmod 755 "$PIDDIR"
|
||||
fi
|
||||
log_daemon_msg "Starting $DESC"
|
||||
if start-stop-daemon \
|
||||
--chuid $RUNAS: --quiet --start \
|
||||
--user $RUNAS --pidfile "$PIDFILE" \
|
||||
--quiet --start --user $RUNAS --pidfile "$PIDFILE" \
|
||||
--startas "$PYTHON_EXEC" -- "$DAEMON" $OPTIONS
|
||||
then log_end_msg 0
|
||||
else log_end_msg 1
|
||||
|
@ -82,7 +82,7 @@ case "$1" in
|
|||
;;
|
||||
reload | force-reload | restart )
|
||||
"$0" stop
|
||||
sleep 1
|
||||
sleep 3
|
||||
"$0" start
|
||||
;;
|
||||
status )
|
||||
|
|
1
debian/cryptobox-server.postrm
vendored
1
debian/cryptobox-server.postrm
vendored
|
@ -33,6 +33,7 @@ umount_all()
|
|||
|
||||
remove_stuff()
|
||||
{
|
||||
#TODO: remove old log files too (created by logrotate)
|
||||
test -e "$LOG_FILE" && rm "$LOG_FILE"
|
||||
test -e "$WEBLOG_FILE" && rm "$WEBLOG_FILE"
|
||||
test -e "$PID_DIR" && rm -r "$PID_DIR"
|
||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: CryptoBox-Server 0.3\n"
|
||||
"Report-Msgid-Bugs-To: translate@cryptobox.org\n"
|
||||
"POT-Creation-Date: 2006-11-28 05:03+0100\n"
|
||||
"POT-Creation-Date: 2006-12-19 12:35+0100\n"
|
||||
"PO-Revision-Date: 2006-12-18 16:38+0100\n"
|
||||
"Last-Translator: Lars Kruse <lars@systemausfall.org>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -12,10 +12,6 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Pootle 0.10.1\n"
|
||||
|
||||
#: Name
|
||||
msgid "English"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: Title.Top
|
||||
msgid "The CryptoBox"
|
||||
msgstr "Die CryptoBox"
|
||||
|
@ -57,20 +53,36 @@ msgid "The CryptoBox is a project of"
|
|||
msgstr "Die CryptoBox ist ein Projekt von"
|
||||
|
||||
#: Text.ContainerName
|
||||
msgid "Container's name"
|
||||
msgid "Volume's name"
|
||||
msgstr "Name des Datenträgers"
|
||||
|
||||
#: Button.HelpForForm
|
||||
msgid "Get help"
|
||||
msgstr "Hilfe"
|
||||
#: Button.EnableHelp
|
||||
msgid "Enable help"
|
||||
msgstr "Hilfe aktivieren"
|
||||
|
||||
#: Button.DisableHelp
|
||||
msgid "Disable help"
|
||||
msgstr "Hilfe deaktivieren"
|
||||
|
||||
#: AdviceMessage.VolumeIsBusy.Title
|
||||
msgid "Disk is busy"
|
||||
msgstr "Datenträger ist beschäftigt"
|
||||
|
||||
#: AdviceMessage.VolumeIsBusy.Text
|
||||
msgid "This disk is currently busy. Please wait for a moment."
|
||||
msgstr "Der Datenträger ist noch beschäftigt. Warte bitte einen Moment."
|
||||
|
||||
#: AdviceMessage.VolumeIsBusy.Link.Text
|
||||
msgid "Show all disks"
|
||||
msgstr "Zeige alle Datenträger"
|
||||
|
||||
#: WarningMessage.AccessDenied.Title
|
||||
msgid "Invalid access credentials"
|
||||
msgstr "Ungültige Zugangsdaten"
|
||||
|
||||
#: WarningMessage.AccessDenied.Text
|
||||
msgid "Sorry - you are not allowed to do this!"
|
||||
msgstr "Sorry - du darfst dies nicht tun!"
|
||||
msgid "Sorry - you did not enter the right credentials! Maybe you should try the default setting: username=>'admin' / password=>'admin'."
|
||||
msgstr "Tut mir Leid, du hast nicht die richtigen Zugangsdaten eingegeben! (Versuch es mit \"admin\" als Benutzername und als Passwort und ändere das Passwort bald.)"
|
||||
|
||||
#: WarningMessage.EmptyPassword.Title
|
||||
msgid "Missing password"
|
||||
|
@ -105,16 +117,16 @@ msgid "The device you have chosen is invalid!"
|
|||
msgstr "Der ausgewählte Datenträger kann nicht verwendet werden."
|
||||
|
||||
#: WarningMessage.VolumeMayNotBeMounted.Title
|
||||
msgid "The container is mounted"
|
||||
msgstr "Der Datenträger ist geöffnet."
|
||||
msgid "The volume is open"
|
||||
msgstr "Der Datenträger ist geöffnet"
|
||||
|
||||
#: WarningMessage.VolumeMayNotBeMounted.Text
|
||||
msgid "This action is not available while the container is active. Please turn it off first."
|
||||
msgid "This action is not available while the volume is active. Please close it first."
|
||||
msgstr "Diese Aktion kann nicht durchgeführt werden, solange der Datenträger geöffnet ist. Bitte schließe ihn zuvor."
|
||||
|
||||
#: WarningMessage.VolumeMayNotBeMounted.Link.Text
|
||||
msgid "Deactivate volume"
|
||||
msgstr "Schließe den Datenträger"
|
||||
msgid "Close volume"
|
||||
msgstr "Schließe Datenträger"
|
||||
|
||||
#: WarningMessage.InvalidAction.Title
|
||||
msgid "Invalid request"
|
||||
|
@ -208,14 +220,3 @@ msgstr "Diese Aktion kann nicht durchgeführt werden, solange der Datenträger g
|
|||
msgid "Close volume"
|
||||
msgstr "Schließe Datenträger"
|
||||
|
||||
#~ msgid "volume_mount"
|
||||
#~ msgstr "volume_mount"
|
||||
|
||||
#~ msgid "logs"
|
||||
#~ msgstr "logs"
|
||||
|
||||
#~ msgid "partition"
|
||||
#~ msgstr "partition"
|
||||
|
||||
#~ msgid "https"
|
||||
#~ msgstr "https"
|
||||
|
|
|
@ -14,26 +14,30 @@ simple access to your data.
|
|||
The following options control the behaviour of the CryptoBoxWebserver:
|
||||
.TP
|
||||
\fB\-c\fR, \fB\-\-config\fR=\fBFILE\fR
|
||||
Uses the named configuration file.
|
||||
Use the specified configuration file.
|
||||
.TP
|
||||
\fB\-p\fR, \fB\-\-port\fR=\fBPORT\fR
|
||||
Specifiy a port to listen to.
|
||||
Specify a port to listen to. The default port is 8080.
|
||||
.TP
|
||||
\fB\-\-host\fR=\fBHOST\fR
|
||||
Specifiy the interface to listen to by providing a resolvable name or an ip. The server
|
||||
Specify the interface to listen to by providing a resolvable name or an ip. The server
|
||||
listens to all interfaces by default.
|
||||
.TP
|
||||
\fB\-B\fR
|
||||
Run the webserver in the background. Otherwise the terminal will stay attached to the
|
||||
process.
|
||||
Run the webserver in the background. By default the process will stay attached to the
|
||||
terminal.
|
||||
.TP
|
||||
\fB\-u\fR, \fB\-\-user\fR=\fBUSER\fR
|
||||
Run with the permissions of the given user after connecting to the port. You may use a
|
||||
uid or a name.
|
||||
.TP
|
||||
\fB\-q\fR
|
||||
Quiet output - only errors will get reported.
|
||||
.TP
|
||||
\fB\-\-pidfile\fR=\fFILE\fR
|
||||
\fB\-\-pidfile\fR=\fBFILE\fR
|
||||
Specify a pid file for the webserver.
|
||||
.TP
|
||||
\fB\-\-datadir\fR=\fDIRECTORY\fR
|
||||
\fB\-\-datadir\fR=\fBDIRECTORY\fR
|
||||
Specify the location of the data directory of the webserver. The default location is
|
||||
\fI/usr/share/cryptobox/www-data\fR.
|
||||
.TP
|
||||
|
|
|
@ -10,5 +10,5 @@ __all__ = ['core', 'web', 'plugins', 'tests']
|
|||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
__version__ = "0.3.0.1"
|
||||
__version__ = "0.3.1"
|
||||
|
||||
|
|
|
@ -574,7 +574,7 @@ class CryptoBoxContainer:
|
|||
def __umount_plain(self):
|
||||
"umount a plaintext partition"
|
||||
if not self.is_mounted():
|
||||
self.cbox.log.info("trying to umount while volume (%s) is mounted" % \
|
||||
self.cbox.log.info("trying to umount while volume (%s) is not mounted" % \
|
||||
self.get_device())
|
||||
return
|
||||
self.cbox.send_event_notification("preumount", self.__get_event_args())
|
||||
|
|
|
@ -66,12 +66,13 @@ class CryptoBox:
|
|||
self.log.info("Umounting all volumes ...")
|
||||
self.reread_container_list()
|
||||
for cont in self.get_container_list():
|
||||
cont.umount()
|
||||
if cont.is_mounted():
|
||||
cont.umount()
|
||||
## save all settings
|
||||
self.log.info("Storing local settings ...")
|
||||
## problems with storing are logged automatically
|
||||
self.prefs.write()
|
||||
if self.prefs.get_active_partition:
|
||||
if self.prefs.get_active_partition():
|
||||
self.prefs.umount_partition()
|
||||
## shutdown logging as the last step
|
||||
try:
|
||||
|
|
|
@ -601,6 +601,9 @@ class MiscConfigFile:
|
|||
def save(self):
|
||||
"""Save a configuration file to disk.
|
||||
"""
|
||||
## overriding of ro-files is not necessary (e.g. samba-include.conf)
|
||||
if os.path.exists(self.filename) and not os.access(self.filename, os.W_OK):
|
||||
return True
|
||||
save_dir = os.path.dirname(self.filename)
|
||||
## create the directory, if necessary
|
||||
if not os.path.isdir(save_dir):
|
||||
|
|
|
@ -98,8 +98,10 @@ class WebInterfaceSites:
|
|||
def cleanup(self):
|
||||
"""Shutdown the webinterface safely.
|
||||
"""
|
||||
self.cbox.log.info("Shutting down webinterface ...")
|
||||
for plugin in self.__plugin_manager.get_plugins():
|
||||
if plugin:
|
||||
self.cbox.log.info("Cleaning up plugin '%s' ..." % plugin.get_name())
|
||||
plugin.cleanup()
|
||||
self.cbox.cleanup()
|
||||
|
||||
|
|
Loading…
Reference in a new issue