-
Notifications
You must be signed in to change notification settings - Fork 0
/
sbam.py
executable file
·173 lines (147 loc) · 5.53 KB
/
sbam.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python
"""
Simple Backup Manager.
The main class interprets user's arguments as request for the agents.
"""
__author__ = "d33pcode"
__copyright__ = "Copyright 2016, HiddenHost"
__license__ = "GPL"
__version__ = "1.0"
__status__ = "Prototype"
__date__ = "2016-10-10"
import argparse
import datetime
import logging
import os
import sys
from getpass import getpass
from tabulate import tabulate
from agents import compressor, encrypter
from agents.databasemanager import DatabaseManager
from agents.utils import questions
from agents.utils.progressbar import ProgressBar
def backup_table(n):
"""
A list of the first n backups.
"""
db_manager = DatabaseManager()
table = db_manager.listBackups(n)
if not table:
logging.info("There are no backups here.")
return
else:
headers = ['backup path', 'original path', 'date']
return tabulate(table, headers, tablefmt="fancy_grid")
def backup(folder, encrypt, forget):
"""
Creates a new backup.
folder:
the path to the folder to compress
encrypt:
encrypts the folder if True
forget:
does not create a new database entry if True
"""
path = os.path.realpath(folder)
if not (os.path.isdir(path)):
sys.exit('Please specify a folder.')
path_dirs = path.split('/')
dirname = path_dirs[len(path_dirs) - 1]
logging.info('Compressing ' + dirname + '...')
compressed_path = compressor.compress(path)
if (compressed_path):
logging.info('Done.')
if encrypt:
key = getpass('Insert a password: ')
encrypter.encrypt(compressed_path, key)
logging.info('Backup encrypted.')
if not forget:
logging.debug('Updating the database...')
today = datetime.datetime.today().isoformat().split('.')[0]
db_manager = DatabaseManager()
db_manager.handleTransaction("INSERT OR IGNORE INTO backups(file_path, original_path, backup_date, encrypted) VALUES(\'" +
compressed_path + "\', \'" + path + "\', \'" + today + "\', " + str(int(encrypt)) + ")")
logging.info('Database updated.')
else:
logging.debug(
'FORGET option specified: backup not saved to database.')
return compressed_path
def restore(folder):
"""
Restores a backup.
folder:
the path to the folder to decompress
"""
db_manager = DatabaseManager()
backup_path = ''
original_path = ''
if folder == 'last_backup':
table = db_manager.listBackups(n=1, enc=True)
if not table:
sys.exit('There are no backups in the database.')
else:
table = db_manager.listBackups(n=1, backup_path=folder, enc=True)
if not table:
q = folder + " is not a registered backup. Do you want to restore it anyway?"
restore = questions.queryYesNo(q, default="no")
if restore:
backup_path = folder
original_path = questions.askForInput(
"Insert the restore path.")
else:
sys.exit('Restore canceled.')
if not backup_path:
backup_path = table[0][0]
if not original_path:
original_path = table[0][1]
enc = table[0][-1]
logging.debug("backup path: " + backup_path)
logging.debug("original path: " + original_path)
if enc:
logging.info('The selected backup is encrypted.')
# add support for wrong passwords!
key = getpass('Insert the password: ')
logging.debug('Decrypting...')
encrypter.decrypt(backup_path + ".enc", backup_path, key)
logging.debug('Decompressing...')
compressor.decompress(backup_path, restore_path=original_path)
logging.info('Backup restored to ' + original_path)
def verbosity(v):
l = logging.DEBUG if v else logging.INFO
return logging.basicConfig(format='%(message)s', level=l)
if __name__ == '__main__':
if not os.geteuid() == 0: # check root privileges
sys.exit('Administrator privileges are required.')
parser = argparse.ArgumentParser(
prog='sbam',
description='Simple Backup Manager.',
epilog='Enjoy.',
)
parser.add_argument('-l', '--list', dest='entries_number', type=int,
nargs='?', const=3, help='List the last N backups (default: 3)')
parser.add_argument('-f', '--folder', dest='folder',
help='The folder to backup')
parser.add_argument('-r', '--restore', dest='backup_path', nargs='?', const='last_backup',
help='Restore a backup from [BACKUP_PATH] if exists (default: last backup)')
# parser.add_argument('-d', '--drive', dest='drive_path', help = 'Specify
# an external drive for backup')
parser.add_argument('-e', '--encrypt',
help='Encrypt the folder', action='store_true')
parser.add_argument(
'-F', '--forget', help="Don't save this backup in the database", action='store_true')
parser.add_argument('-v', '--verbose',
help='Display verbose output', action='store_true')
args = parser.parse_args()
if not (args.folder or args.backup_path or args.entries_number):
sys.exit(parser.print_help())
# LOGGING
verbosity(args.verbose)
# BACKUP
if args.folder:
backup(args.folder, args.encrypt, args.forget)
# RESTORE
elif args.backup_path:
restore(args.backup_path)
# LIST
if args.entries_number:
print backup_table(args.entries_number)