reject bad index files with a meaningful error
[python-delta-tar] / backup.py
CommitLineData
e4a93a2f
ERE
1#!/usr/bin/env python3
2
3# Copyright (C) 2013 Intra2net AG
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published
7# by the Free Software Foundation; either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Lesser General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see
17# <http://www.gnu.org/licenses/lgpl-3.0.html>
18
10c70dc6
ERE
19import argparse
20import binascii
21import json
22import logging
23import os
24import re
25import random
26import shutil
174794cc 27import sys
10c70dc6
ERE
28from datetime import datetime
29from functools import partial
30
31from deltatar.deltatar import DeltaTar, NO_MATCH, MATCH, PARENT_MATCH
32from deltatar.tarfile import TarFile, GNU_FORMAT
33
10c70dc6
ERE
34consoleLogger = logging.StreamHandler()
35consoleLogger.setLevel(logging.DEBUG)
36
37def check_equal_dirs(path1, path2, deltatar):
38 '''
39 compare the two directories source_dir and target_dir and check
40 # they are the same
41 '''
42 nbars1 = len(path1.split('/'))
43 nbars2 = len(path2.split('/'))
44
45 source_it = deltatar._recursive_walk_dir(path1)
46 source_it = deltatar.jsonize_path_iterator(source_it, strip=nbars1)
47 target_it = deltatar._recursive_walk_dir(path2)
48 target_it = deltatar.jsonize_path_iterator(target_it, strip=nbars2)
49 while True:
50 try:
e4a93a2f
ERE
51 sitem = next(source_it)
52 titem = next(target_it)
10c70dc6
ERE
53 except StopIteration:
54 try:
e4a93a2f 55 titem = next(target_it)
10c70dc6
ERE
56 raise Exception("iterators do not stop at the same time")
57 except StopIteration:
58 break
59 try:
60 assert deltatar._equal_stat_dicts(sitem, titem)
e4a93a2f
ERE
61 except Exception as e:
62 print(sitem)
63 print(titem)
64 print("FAIL")
10c70dc6
ERE
65 raise
66
67if __name__ == "__main__":
1046c582
ERE
68 #import tracemalloc
69 #tracemalloc.enable()
70 #top = tracemalloc.DisplayTop(25)
71 #top.show_lineno = True
253d4cdd 72 #top.start(20)
10c70dc6
ERE
73 parser = argparse.ArgumentParser()
74
75 parser.add_argument("-m", "--mode", default='',
47fb2d67
PG
76 help=
77 """Mode in which to read/write the backup.
78 Valid modes are:
79 '' open uncompressed;
80 'gz' open with gzip compression;
81 'bz2' open with bzip2 compression;
e0631598
PG
82 '#gz' encrypted stream of individually
83 compressed tar blocks.
84 To enable encryption, supply a password.
47fb2d67
PG
85 """)
86 parser.add_argument("-t", "--targetpath", help="Target path directory.")
87 parser.add_argument("-s", "--sourcepath", help="Source path directory.")
ecb9676d
PG
88 epw = os.getenv ("PDTCRYPT_PASSWORD")
89 parser.add_argument("-p", "--password",
90 default=epw.strip () if epw is not None else None,
91 help="Password for symmetric encryption. "
92 "The environment variable PDTCRYPT_PASSWORD should "
e0631598 93 "be preferred to this. Enables encryption.")
47fb2d67
PG
94 parser.add_argument("-v", "--volsize", default=None,
95 help="Maximum volume size, in megabytes.")
96 parser.add_argument("-r", "--restore", action='store_true',
97 help="Restore a backup.")
e93f83f1
PG
98 parser.add_argument("-R", "--recover", action='store_true',
99 help="Restore a backup with an index file.")
47fb2d67
PG
100 parser.add_argument("-f", "--full", action='store_true',
101 help="Create a full backup.")
102 parser.add_argument("-d", "--diff", action='store_true',
103 help="Create a diff backup.")
104 parser.add_argument("-i", "--indexes", nargs='+', help="Indexes paths.")
105 parser.add_argument("-l", "--list-files", action='store_true',
106 help="List files in a tarball.")
8c65a2b1 107 parser.add_argument("-x", "--excluded", nargs='+', default=[],
47fb2d67 108 help="Files to exclude from backup.")
4cbed687 109 parser.add_argument("-inc", "--included", nargs='+', default=[],
47fb2d67 110 help="Files to include in the backup.")
4cbed687 111 parser.add_argument("-ip", "--included-path", default=None,
47fb2d67 112 help="Path to a file containing a list of included paths.")
8c65a2b1 113 parser.add_argument("-xp", "--excluded-path", default=None,
47fb2d67
PG
114 help="Path to a file containing a list of excluded paths.")
115 parser.add_argument("-e", "--equals", action='store_true',
116 help="Check if two dirs are equal.")
10c70dc6
ERE
117
118 args = parser.parse_args()
8c65a2b1
ERE
119
120 if args.excluded_path:
121 f = open(args.excluded_path, 'r')
122 excluded_files = f.readlines()
123 f.close()
124 else:
125 excluded_files = args.excluded
126
4cbed687
ERE
127 if args.included_path:
128 f = open(args.included_path, 'r')
129 included_files = f.readlines()
130 f.close()
131 else:
132 included_files = args.included
133
8c65a2b1 134 deltatar = DeltaTar(mode=args.mode, password=args.password,
4cbed687
ERE
135 logger=consoleLogger, excluded_files=excluded_files,
136 included_files=included_files)
10c70dc6
ERE
137
138 if args.full:
139 deltatar.create_full_backup(args.sourcepath, args.targetpath, args.volsize)
140 elif args.diff:
141 deltatar.create_diff_backup(args.sourcepath, args.targetpath, args.indexes[0], args.volsize)
8c65a2b1 142 elif args.list_files:
ec96293d 143 deltatar.list_backup(args.sourcepath, lambda e: print (e.name))
10c70dc6
ERE
144 elif args.restore:
145 if args.indexes is not None:
146 deltatar.restore_backup(args.targetpath, backup_indexes_paths=args.indexes)
147 else:
148 deltatar.restore_backup(args.targetpath, backup_tar_path=args.sourcepath)
e93f83f1 149 elif args.recover:
174794cc
PG
150 if args.sourcepath is not None:
151 print("Disaster recovery conflicts with --sourcepath; please supply"
152 " an\nindex file (--indexes).", file=sys.stderr)
e93f83f1 153 failed = deltatar.recover_backup(args.targetpath,
174794cc 154 backup_indexes_paths=args.indexes)
e93f83f1
PG
155 if len (failed) > 0:
156 logger = logging.getLogger('deltatar.DeltaTar')
157 print ("%d files could not be restored:" % len (failed))
158 for i, f in enumerate (failed):
159 print (" [%d] %s (%s)" % (i, f [0], f [1]))
160
10c70dc6 161 elif args.equals:
1817bfb4
PG
162 check_equal_dirs(os.path.abspath(args.sourcepath), os.path.abspath(args.targetpath), deltatar)
163 else:
1817bfb4
PG
164 print("Nothing to do.\nPlease specify one of --full, --diff, --list-files, "
165 "--restore, --equals.\n", file=sys.stderr)
166 parser.print_help(file=sys.stderr)
167
e93f83f1 168