Commit e0056c74 authored by Irene "Tissy" Pirrotta's avatar Irene "Tissy" Pirrotta
Browse files

Added common directory

parent e657ae4a
This diff is collapsed.
# backintime
Backup tool based on rsync
\ No newline at end of file
# Back In Time
# Copyright (C) 2008-2019 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze
#
# 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.
import os
import fcntl
import errno
import logger
import tools
class ApplicationInstance:
"""
Class used to handle one application instance mechanism.
Args:
pidFile (str): full path of file used to save pid and procname
autoExit (bool): automatically call sys.exit if there is an other
instance running
flock (bool): use file-locks to make sure only one instance
is checking at the same time
"""
def __init__(self, pidFile, autoExit = True, flock = False):
self.pidFile = pidFile
self.pid = 0
self.procname = ''
self.flock = None
if flock:
self.flockExclusiv()
if autoExit:
if self.check(True):
self.startApplication()
def __del__(self):
self.flockUnlock()
def check(self, autoExit = False):
"""
Check if the current application is already running
Args:
autoExit (bool): automatically call sys.exit if there is an other
instance running
Returns:
bool: ``True`` if this is the only application
instance
"""
#check if the pidfile exists
if not os.path.isfile(self.pidFile):
return True
self.pid, self.procname = self.readPidFile()
#check if the process with specified by pid exists
if 0 == self.pid:
return True
if not tools.processAlive(self.pid):
return True
#check if the process has the same procname
#check cmdline for backwards compatibility
if self.procname and \
self.procname != tools.processName(self.pid) and \
self.procname != tools.processCmdline(self.pid):
return True
if autoExit:
#exit the application
print("The application is already running !")
exit(0) #exit raise an exception so don't put it in a try/except block
return False
def busy(self):
"""
Check if one application with this instance is currently running.
Returns:
bool: ``True`` if an other instance is currently running.
"""
return not self.check()
def startApplication(self):
"""
Called when the single instance starts to save its pid
"""
pid = os.getpid()
procname = tools.processName(pid)
try:
with open(self.pidFile, 'wt') as f:
f.write('{}\n{}'.format(pid, procname))
except OSError as e:
logger.error('Failed to write PID file %s: [%s] %s' %(e.filename, e.errno, e.strerror))
self.flockUnlock()
def exitApplication(self):
"""
Called when the single instance exit (remove pid file)
"""
try:
os.remove(self.pidFile)
except:
pass
def flockExclusiv(self):
"""
Create an exclusive lock to block a second instance while
the first instance is starting.
"""
try:
self.flock = open(self.pidFile + '.flock', 'w')
fcntl.flock(self.flock, fcntl.LOCK_EX)
except OSError as e:
logger.error('Failed to write flock file %s: [%s] %s' %(e.filename, e.errno, e.strerror))
def flockUnlock(self):
"""
Remove the exclusive lock. Second instance can now continue
but should find it self to be obsolete.
"""
if self.flock:
fcntl.fcntl(self.flock, fcntl.LOCK_UN)
self.flock.close()
try:
os.remove(self.flock.name)
except:
#an other instance was faster
#race condition while using 'if os.path.exists(...)'
pass
self.flock = None
def readPidFile(self):
"""
Read the pid and procname from the file
Returns:
tuple: tuple of (pid(int), procname(str))
"""
pid = 0
procname = ''
try:
with open(self.pidFile, 'rt') as f:
data = f.read()
data = data.split('\n', 1)
if data[0].isdigit():
pid = int(data[0])
if len(data) > 1:
procname = data[1].strip('\n')
except OSError as e:
logger.warning('Failed to read PID and process name from %s: [%s] %s' %(e.filename, e.errno, e.strerror))
except ValueError as e:
logger.warning('Failed to extract PID and process name from %s: %s'
%(self.pidFile, str(e)))
return (pid, procname)
if __name__ == '__main__':
import time
#create application instance
appInstance = ApplicationInstance('/tmp/myapp.pid')
#do something here
print("Start MyApp")
time.sleep(5) #sleep 5 seconds
print("End MyApp")
#remove pid file
appInstance.exitApplication()
# Copyright (C) 2012-2019 Germar Reitze
#
# 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.
import os
import sys
try:
import gtk
except:
pass
import password
import password_ipc
import tools
import config
if __name__ == '__main__':
"""
return password.
"""
cfg = config.Config()
tools.envLoad(cfg.cronEnvFile())
profile_id = os.getenv('ASKPASS_PROFILE_ID', '1')
mode = os.getenv('ASKPASS_MODE', 'local')
if mode == 'USER':
prompt = os.getenv('ASKPASS_PROMPT', None)
pw = password.Password(cfg)
print(pw.passwordFromUser(None, prompt = prompt))
sys.exit(0)
temp_file = os.getenv('ASKPASS_TEMP')
if temp_file is None:
#normal mode, get password from module password
pw = password.Password(cfg)
print(pw.password(None, profile_id, mode))
sys.exit(0)
#temp mode
fifo = password_ipc.FIFO(temp_file)
pw = fifo.read(5)
if pw:
print(pw)
#!/bin/sh
# Back In Time
# Copyright (C) 2008-2019 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze
#
# 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.
CUR_PATH="$(dirname $(readlink -m $0))"
if [ -f "${CUR_PATH}/backintime.py" ]; then
APP_PATH=$CUR_PATH
else
APP_PATH=$(readlink -m "${CUR_PATH}/../share/backintime/common")
fi
python3 -Es $APP_PATH/backintime.py "$@"
#!/bin/sh
# Back In Time
# Copyright (C) 2008-2019 Oprea Dan, Bart de Koning, Richard Bailey, Germar Reitze
#
# 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.
#fixing gray window error
#https://launchpad.net/bugs/1493020
export QT_GRAPHICSSYSTEM="native"
CUR_PATH="$(dirname $(readlink -m $0))"
if [ -f "${CUR_PATH}/askpass.py" ]; then
APP_PATH=$CUR_PATH
else
APP_PATH=$(readlink -m "${CUR_PATH}/../share/backintime/common")
fi
python3 -Es $APP_PATH/askpass.py "$@"
[Desktop Entry]
Version=1.0
Name=Backintime Password Cache
Exec=/bin/sh -c "backintime pw-cache start 2>&1 >/dev/null"
Comment=Cache passwords for non-interactive Backintime cronjobs
Icon=gtk-save
Terminal=false
Type=Application
This diff is collapsed.
#!/usr/bin/env python3
# Copyright (C) 2015-2019 Germar Reitze
#
# 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.
import sys
if sys.stdout.isatty():
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
else:
HEADER = ''
OKBLUE = ''
OKGREEN = ''
WARNING = ''
FAIL = ''
ENDC = ''
BOLD = ''
UNDERLINE = ''
# -*- coding: utf-8 -*-
# Back In Time
# Copyright (C) 2012-2019 Germar Reitze
#
# 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.
import os
import sys
import tools
import snapshots
import bcolors
def restore(cfg, snapshot_id = None, what = None, where = None, **kwargs):
if what is None:
what = input('File to restore: ')
what = tools.preparePath(os.path.abspath(os.path.expanduser(what)))
if where is None:
where = input('Restore to (empty for original path): ')
if where:
where = tools.preparePath(os.path.abspath(os.path.expanduser(where)))
snapshotsList = snapshots.listSnapshots(cfg)
sid = selectSnapshot(snapshotsList, cfg, snapshot_id, 'SnapshotID to restore')
print('')
RestoreDialog(cfg, sid, what, where, **kwargs).run()
def remove(cfg, snapshot_ids = None, force = None):
snapshotsList = snapshots.listSnapshots(cfg)
if not snapshot_ids:
snapshot_ids = (None,)
sids = [selectSnapshot(snapshotsList, cfg, sid, 'SnapshotID to remove') for sid in snapshot_ids]
if not force:
print('Do you really want to remove this snapshots?')
[print(sid.displayName) for sid in sids]
if not 'yes' == input('(no/yes): '):
return
s = snapshots.Snapshots(cfg)
[s.remove(sid) for sid in sids]
def checkConfig(cfg, crontab = True):
import mount
from exceptions import MountException
def announceTest():
print()
print(frame(test))
def failed():
print(test + ': ' + bcolors.FAIL + 'failed' + bcolors.ENDC)
def okay():
print(test + ': ' + bcolors.OKGREEN + 'done' + bcolors.ENDC)
def errorHandler(msg):
print(bcolors.WARNING + 'WARNING: ' + bcolors.ENDC + msg)
cfg.setErrorHandler(errorHandler)
mode = cfg.snapshotsMode()
if cfg.SNAPSHOT_MODES[mode][0] is not None:
#preMountCheck
test = 'Run mount tests'
announceTest()
mnt = mount.Mount(cfg = cfg, tmp_mount = True)
try:
mnt.preMountCheck(mode = mode, first_run = True)
except MountException as ex:
failed()
print(str(ex))
return False
okay()
#okay, lets try to mount
test = 'Mount'
announceTest()
try:
hash_id = mnt.mount(mode = mode, check = False)
except MountException as ex:
failed()
print(str(ex))
return False
okay()
test = 'Check/prepair snapshot path'
announceTest()
snapshots_path = cfg.snapshotsPath(mode = mode, tmp_mount = True)
if not cfg.setSnapshotsPath(snapshots_path, mode = mode):
failed()
return False
okay()
#umount
if not cfg.SNAPSHOT_MODES[mode][0] is None:
test = 'Unmount'
announceTest()
try:
mnt.umount(hash_id = hash_id)
except MountException as ex:
failed()
print(str(ex))
return False
okay()
test = 'Check config'
announceTest()
if not cfg.checkConfig():
failed()
return False
okay()
if crontab:
test = 'Install crontab'
announceTest()
if not cfg.setupCron():
failed()
return False
okay()
return True
def selectSnapshot(snapshotsList, cfg, snapshot_id = None, msg = 'SnapshotID'):
"""
check if given snapshot is valid. If not print a list of all
snapshots and ask to choose one
"""
len_snapshots = len(snapshotsList)
if not snapshot_id is None:
try:
sid = snapshots.SID(snapshot_id, cfg)
if sid in snapshotsList:
return sid
else:
print('SnapshotID %s not found.' % snapshot_id)
except ValueError:
try:
index = int(snapshot_id)
return snapshotsList[index]
except (ValueError, IndexError):
print('Invalid SnaphotID index: %s' % snapshot_id)
snapshot_id = None
columns = (terminalSize()[1] - 25) // 26 + 1
rows = len_snapshots // columns
if len_snapshots % columns > 0:
rows += 1
print('SnapshotID\'s:')
for row in range(rows):
line = []
for column in range(columns):
index = row + column * rows
if index > len_snapshots - 1:
continue
line.append('{i:>4}: {s}'.format(i = index, s = snapshotsList[index]))
print(' '.join(line))
print('')
while snapshot_id is None:
try:
index = int(input(msg + ' (0 - %d): ' % (len_snapshots - 1)))
snapshot_id = snapshotsList[index]
except (ValueError, IndexError):
print('Invalid Input')
continue
return snapshot_id
def terminalSize():
"""
get terminal size
"""
for fd in (sys.stdin, sys.stdout, sys.stderr):
try:
import fcntl, termios, struct
return [int(x) for x in struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))]
except:
pass
return [24, 80]
def frame(msg, size = 32):
ret = ' +' + '-' * size + '+\n'
ret += ' |' + msg.center(size) + '|\n'
ret += ' +' + '-' * size + '+'
return ret
class RestoreDialog(object):
def __init__(self, cfg, sid, what, where, **kwargs):
self.config = cfg
self.sid = sid
self.what = what
self.where = where
self.kwargs = kwargs
self.logFile = self.config.restoreLogFile()
if os.path.exists(self.logFile):
os.remove(self.logFile)
def callback(self, line, *params):
if not line:
return
print(line)
with open(self.logFile, 'a') as log:
log.write(line + '\n')
def run(self):
s = snapshots.Snapshots(self.config)
s.restore(self.sid, self.what, self.callback, self.where, **self.kwargs)
print('\nLog saved to %s' % self.logFile)
class BackupJobDaemon(tools.Daemon):
def __init__(self, func, args):
super(BackupJobDaemon, self).__init__()
self.func = func
self.args = args
def run(self):
self.func(self.args, False)
profile1.snapshots.automatic_backup_day=1
profile1.snapshots.automatic_backup_mode=0
profile1.snapshots.automatic_backup_time=0
profile1.snapshots.automatic_backup_weekday=7
profile1.snapshots.backup_on_restore.enabled=true
profile1.snapshots.bwlimit.enabled=false
profile1.snapshots.bwlimit.value=3000
profile1.snapshots.continue_on_errors=true
profile1.snapshots.copy_links=false
profile1.snapshots.copy_unsafe_links=false
profile1.snapshots.cron.ionice=true
profile1.snapshots.cron.nice=true
profile1.snapshots.custom_backup_time=8,12,18,23
profile1.snapshots.dont_remove_named_snapshots=true
profile1.snapshots.exclude.1.value=.gvfs
profile1.snapshots.exclude.10.value=/proc/*
profile1.snapshots.exclude.11.value=/sys/*
profile1.snapshots.exclude.12.value=/dev/*
profile1.snapshots.exclude.13.value=/run/*
profile1.snapshots.exclude.2.value=.cache*
profile1.snapshots.exclude.3.value=[Cc]ache*
profile1.snapshots.exclude.4.value=.thumbnails*
profile1.snapshots.exclude.5.value=[Tt]rash*
profile1.snapshots.exclude.6.value=*.backup*
profile1.snapshots.exclude.7.value=*~
profile1.snapshots.exclude.8.value=/home/USER/Ubuntu One
profile1.snapshots.exclude.9.value=.dropbox*