qdumpfs 0.5.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/Gemfile.lock +3 -3
- data/README.md +22 -16
- data/data/from/0.txt +1 -0
- data/data/from/a/1.txt +1 -0
- data/exe/sample +40 -0
- data/lib/qdumpfs.rb +81 -76
- data/lib/qdumpfs/option.rb +33 -4
- data/lib/qdumpfs/util.rb +16 -12
- data/lib/qdumpfs/version.rb +4 -3
- data/run_qdumpfs.sh +1 -1
- data/sample.sh +5 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5a538d62022eefe0216aeebb5a145a9e58da17fec71b6e5568a05e6e3f0e5234
|
|
4
|
+
data.tar.gz: c4998bacaa329ddbccf59e97ffacc1f70f6c9e0e771a5684bce9b1231dbf1539
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa1a042fa12c461a65f66757ecc1966976672947d88de8e885141e128eea04c2d8cbdea9f833e3da5c52b28a28d24047e17142f12af47e204f9317ae04bd571b
|
|
7
|
+
data.tar.gz: 82467662b3415937881e00f85396783e096d6c3643a6bf5a469e9cae931887087edc6ba54795c1296097342f03c896a69e6223fe0697f6e9a3760109033c90e9
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Qdumpfs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
pdumpfsの個人的改良版です。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Gem化して最近のバージョンのバージョンのRubyに対応。コマンドの拡張などを行っています。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## インストール
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
gem install qdumpfs
|
|
10
10
|
|
|
11
|
+
## 使用方法
|
|
11
12
|
|
|
12
13
|
```
|
|
13
14
|
Usage: qdumpfs [options] <source> <dest>
|
|
@@ -19,48 +20,53 @@ Options
|
|
|
19
20
|
-e, --exclude=PATTERN exclude files/directories matching PATTERN
|
|
20
21
|
-s, --exclude-by-size=SIZE exclude files larger than SIZE
|
|
21
22
|
-w, --exclude-by-glob=GLOB exclude files matching GLOB
|
|
22
|
-
-c, --command=COMMAND backup|sync|list|expire|verify|
|
|
23
|
+
-c, --command=COMMAND backup|sync|list|expire|verify|delete
|
|
23
24
|
-l, --limit=HOURS limit hours
|
|
24
25
|
-k, --keep=KEEPARG ex: --keep 100Y12M12W30D (100years, 12months, 12weeks, 30days, default)
|
|
25
26
|
```
|
|
26
27
|
|
|
27
|
-
##
|
|
28
|
+
## 実行例
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
バックアップを実行する場合。
|
|
28
32
|
|
|
29
|
-
Backup your home directory, run the following command.
|
|
30
33
|
```
|
|
31
34
|
qdumpfs /home/foo /backup
|
|
32
35
|
```
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
"--command backup"オプションを明示することもできます。
|
|
38
|
+
|
|
35
39
|
```
|
|
36
40
|
qdumpfs --command=backup /home/foo /backup
|
|
37
41
|
```
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
"--command sync"でバックアップフォルダを同期できます。
|
|
40
44
|
```
|
|
41
45
|
qdumpfs --command=sync /backup1 /backup2
|
|
42
46
|
```
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
バックアップフォルダの同期には膨大な時間が必要な場合があるため、実行時間を制限できます。以下は例えば1時間に制限する場合です。
|
|
45
49
|
```
|
|
46
50
|
qdumpfs --command=sync --limit=1 /backup1 /backup2
|
|
47
51
|
```
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
バックアップフォルダの同期で、1時間でかつ"100Y12M12W30D"を保存する場合のオプションです。
|
|
50
54
|
```
|
|
51
|
-
qdumpfs --command=sync --limit=1 --keep=5Y6M7W10D
|
|
55
|
+
qdumpfs --command=sync --limit=1 --keep=5Y6M7W10D backup1 /backup2
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
"--command expire"で、"--keep="パターンに該当しないバックアップを削除できます。
|
|
55
59
|
```
|
|
56
|
-
qdumpfs --command=expire --limit=1 --keep=5Y6M7W10D
|
|
60
|
+
qdumpfs --command=expire --limit=1 --keep=5Y6M7W10D backup1 /backup2
|
|
57
61
|
```
|
|
58
62
|
|
|
63
|
+
"--command delete"で、バックアップに存在する指定したパスを削除できます(間違えてバックアップした内容を削除したい場合などに使用)。
|
|
64
|
+
```
|
|
65
|
+
qdumpfs --command=delete --delete-dir=backup1 --limit=1 r:/backup2
|
|
66
|
+
```
|
|
59
67
|
|
|
60
68
|
## License
|
|
61
69
|
|
|
62
70
|
qdumpfs is a free software with ABSOLUTELY NO WARRANTY under the terms of the GNU General Public License version 2.
|
|
63
71
|
|
|
64
72
|
|
|
65
|
-
|
|
66
|
-
|
data/data/from/0.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0
|
data/data/from/a/1.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1
|
data/exe/sample
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require "qdumpfs"
|
|
5
|
+
|
|
6
|
+
from = "./data/from"
|
|
7
|
+
to = "./data/to"
|
|
8
|
+
to2 = "./data/to2"
|
|
9
|
+
|
|
10
|
+
def create_dir(dir)
|
|
11
|
+
if FileTest.directory?(dir)
|
|
12
|
+
FileUtils.rm_rf(dir)
|
|
13
|
+
end
|
|
14
|
+
FileUtils.mkpath(dir)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
create_dir(to)
|
|
18
|
+
create_dir(to2)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
arg = ["--backup-at=20210119", from, to]
|
|
22
|
+
Qdumpfs::Command.run(arg)
|
|
23
|
+
arg = ["--backup-at=20210121", from, to]
|
|
24
|
+
Qdumpfs::Command.run(arg)
|
|
25
|
+
arg = ["--backup-at=20210122", from, to]
|
|
26
|
+
Qdumpfs::Command.run(arg)
|
|
27
|
+
arg = ["--backup-at=20210123", from, to]
|
|
28
|
+
Qdumpfs::Command.run(arg)
|
|
29
|
+
arg = ["--backup-at=20210124", from, to]
|
|
30
|
+
Qdumpfs::Command.run(arg)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
arg = ["--backup-at=20210122", from, to2]
|
|
34
|
+
Qdumpfs::Command.run(arg)
|
|
35
|
+
arg = ["--backup-at=20210123", from, to2]
|
|
36
|
+
|
|
37
|
+
arg = ["--command=delete", "--delete-from=20210122", "--delete-to=20210123", "--limit=1", to, to2]
|
|
38
|
+
Qdumpfs::Command.run(arg)
|
|
39
|
+
|
|
40
|
+
|
data/lib/qdumpfs.rb
CHANGED
|
@@ -34,13 +34,26 @@ module Qdumpfs
|
|
|
34
34
|
}
|
|
35
35
|
opt.on('-s SIZE', '--exclude-by-size=SIZE', 'exclude files larger than SIZE') {|v| opts[:es] = v }
|
|
36
36
|
opt.on('-w GLOB', '--exclude-by-glob=GLOB', 'exclude files matching GLOB') {|v| opts[:ep] = v }
|
|
37
|
-
commands = ['backup', 'sync', 'list', 'expire', 'verify']
|
|
37
|
+
commands = ['backup', 'sync', 'list', 'expire', 'verify', 'delete']
|
|
38
38
|
opt.on('-c COMMAND', '--command=COMMAND', commands, commands.join('|')) {|v| opts[:c] = v}
|
|
39
39
|
opt.on('-l HOURS', '--limit=HOURS', 'limit hours') {|v| opts[:limit] = v}
|
|
40
40
|
opt.on('-k KEEPARG', '--keep=KEEPARG', 'ex: --keep 100Y12M12W30D (100years, 12months, 12weeks, 30days, default)') {|v| opts[:keep] = v}
|
|
41
|
-
opt.on('--logdir
|
|
41
|
+
opt.on('--logdir=LOGDIR', 'logdir') {|v| opts[:logdir] = v}
|
|
42
|
+
opt.on('--delete-from=YYYYMMDD', 'delete backup from YYYY/MM/DD') {|v|
|
|
43
|
+
opts[:delete_from] = Date.parse(v)
|
|
44
|
+
}
|
|
45
|
+
opt.on('--delete-to=YYYYMMDD', 'delete backup to YYYY/MM/DD') {|v|
|
|
46
|
+
opts[:delete_to] = Date.parse(v)
|
|
47
|
+
}
|
|
48
|
+
opt.on('--delete-dir=DIRS', 'relative path from the snapshot root of the backup. ex: --delete-dir=foo,home/bar') {|v|
|
|
49
|
+
opts[:delete_dirs] = v.split(/,/)
|
|
50
|
+
}
|
|
51
|
+
opt.on('--backup-at=YYYYMMDD', 'backup at YYYY/MM/DD') {|v|
|
|
52
|
+
opts[:backup_at] = Date.parse(v)
|
|
53
|
+
}
|
|
54
|
+
opt.on('-d', '--debug', 'debug mode') {|v| opts[:d] = v }
|
|
42
55
|
opt.parse!(argv)
|
|
43
|
-
option = Option.new(opts,
|
|
56
|
+
option = Option.new(opts, argv)
|
|
44
57
|
if opts[:v]
|
|
45
58
|
puts "<<<<< qdumpfs options >>>>> "
|
|
46
59
|
puts "logdir: #{option.logdir}"
|
|
@@ -52,6 +65,10 @@ module Qdumpfs
|
|
|
52
65
|
command = Command.new(option)
|
|
53
66
|
command.run
|
|
54
67
|
rescue => e
|
|
68
|
+
if option.debug
|
|
69
|
+
p e.message
|
|
70
|
+
p e.backtrace
|
|
71
|
+
end
|
|
55
72
|
puts opt.help
|
|
56
73
|
exit
|
|
57
74
|
end
|
|
@@ -69,13 +86,13 @@ module Qdumpfs
|
|
|
69
86
|
elsif @opt.cmd == 'list'
|
|
70
87
|
list
|
|
71
88
|
elsif @opt.cmd == 'expire'
|
|
72
|
-
expire
|
|
89
|
+
delete('expire')
|
|
73
90
|
elsif @opt.cmd == 'verify'
|
|
74
91
|
verify
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
raise RuntimeError, "unknown command: #{cmd}"
|
|
92
|
+
elsif @opt.cmd == 'delete'
|
|
93
|
+
delete('delete')
|
|
94
|
+
else
|
|
95
|
+
raise RuntimeError, "unknown command: #{@opt.cmd}"
|
|
79
96
|
end
|
|
80
97
|
end
|
|
81
98
|
|
|
@@ -136,29 +153,6 @@ module Qdumpfs
|
|
|
136
153
|
return src_count, dst_count
|
|
137
154
|
end
|
|
138
155
|
|
|
139
|
-
def get_snapshots(target_dir)
|
|
140
|
-
# 指定したディレクトリに含まれるバックアップフォルダ(日付つき)を全て取得
|
|
141
|
-
dd = "[0-9][0-9]"
|
|
142
|
-
dddd = dd + dd
|
|
143
|
-
# FIXME: Y10K problem.
|
|
144
|
-
dirs = []
|
|
145
|
-
glob_path = File.join(target_dir, dddd, dd, dd)
|
|
146
|
-
Dir.glob(glob_path).sort.find {|dir|
|
|
147
|
-
day, month, year = File.split_all(dir).reverse.map {|x| x.to_i }
|
|
148
|
-
path = dir
|
|
149
|
-
if File.directory?(path) and Date.valid_date?(year, month, day) and
|
|
150
|
-
dirs << path
|
|
151
|
-
end
|
|
152
|
-
}
|
|
153
|
-
dirs
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def get_snapshot_date(snapshot)
|
|
157
|
-
# バックアップディレクトリのパス(日付つき)から日付を取得して返す
|
|
158
|
-
day, month, year = File.split_all(snapshot).reverse.map {|x| x.to_i }
|
|
159
|
-
Time.new(year, month, day)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
156
|
def update_snapshot(src, latest, today)
|
|
163
157
|
# バックアップの差分コピーを実行
|
|
164
158
|
# src: コピー元ディレクトリ ex) i:/from/home
|
|
@@ -179,7 +173,7 @@ module Qdumpfs
|
|
|
179
173
|
# ファイルのアップデート
|
|
180
174
|
update_file(s, l, t)
|
|
181
175
|
dirs[t] = File.stat(s) if File.ftype(s) == "directory"
|
|
182
|
-
rescue
|
|
176
|
+
rescue => e
|
|
183
177
|
wprintf("%s: %s", src, e.message)
|
|
184
178
|
next
|
|
185
179
|
end
|
|
@@ -214,7 +208,7 @@ module Qdumpfs
|
|
|
214
208
|
end
|
|
215
209
|
chown_if_root(type, s, t)
|
|
216
210
|
dirs[t] = File.stat(s) if File.ftype(s) == "directory"
|
|
217
|
-
rescue
|
|
211
|
+
rescue => e
|
|
218
212
|
wprintf("%s: %s", s, e.message)
|
|
219
213
|
next
|
|
220
214
|
end
|
|
@@ -296,6 +290,9 @@ module Qdumpfs
|
|
|
296
290
|
|
|
297
291
|
@written_bytes = 0
|
|
298
292
|
start_time = Time.now
|
|
293
|
+
if @opt.backup_at
|
|
294
|
+
start_time = to_time(@opt.backup_at)
|
|
295
|
+
end
|
|
299
296
|
src = @opt.src
|
|
300
297
|
dst = @opt.dst
|
|
301
298
|
|
|
@@ -439,74 +436,80 @@ module Qdumpfs
|
|
|
439
436
|
file.close
|
|
440
437
|
end
|
|
441
438
|
|
|
442
|
-
def
|
|
439
|
+
def delete(cmd)
|
|
443
440
|
@opt.validate_directories(1)
|
|
444
|
-
|
|
445
441
|
start_time = Time.now
|
|
446
442
|
limit_time = start_time + (@opt.limit_sec)
|
|
447
|
-
log("#####
|
|
448
|
-
|
|
443
|
+
log("##### #{cmd} delete-from=#{@opt.delete_from} delete-to=#{@opt.delete_to} start #{fmt(start_time)} => limit_time=#{fmt(limit_time)} #####")
|
|
449
444
|
@opt.dirs.each do |target_dir|
|
|
450
445
|
|
|
451
446
|
target_start = Time.now
|
|
452
|
-
|
|
447
|
+
delete_target_dir(cmd, target_dir)
|
|
453
448
|
target_end = Time.now
|
|
454
449
|
|
|
455
450
|
# 次回expireにかかる時間を最終expire時間の半分と予想
|
|
456
451
|
next_expire = (target_end - target_start) / 2
|
|
457
452
|
|
|
458
453
|
cur_time = Time.now
|
|
459
|
-
|
|
454
|
+
in_limit = (cur_time + next_expire) < limit_time
|
|
460
455
|
|
|
461
456
|
log("## cur_time=#{fmt(cur_time)} + next_expire=#{next_expire} < limit_time=#{fmt(limit_time)} in_limit=#{in_limit} ## ")
|
|
462
457
|
unless in_limit
|
|
463
458
|
break
|
|
464
459
|
end
|
|
465
460
|
end
|
|
466
|
-
|
|
467
|
-
log("##### expire end #####")
|
|
461
|
+
log("##### #{cmd} end #####")
|
|
468
462
|
end
|
|
469
|
-
|
|
470
|
-
def
|
|
463
|
+
|
|
464
|
+
def rm_dir(path)
|
|
465
|
+
can_delete = true
|
|
466
|
+
if @opt.dry_run
|
|
467
|
+
can_delete = false
|
|
468
|
+
elsif !FileTest.directory?(path)
|
|
469
|
+
can_delete = false
|
|
470
|
+
end
|
|
471
|
+
msg = can_delete ? "...ok..." : "...ng..."
|
|
472
|
+
print "Deleting #{path} #{msg}"
|
|
473
|
+
|
|
474
|
+
return unless can_delete
|
|
475
|
+
|
|
476
|
+
#それ以外は日付バックアップディレクトリ全体を削除
|
|
477
|
+
if windows?
|
|
478
|
+
# Windowsの場合
|
|
479
|
+
win_backup_path = to_win_path(path)
|
|
480
|
+
system("rmdir /S /Q #{win_backup_path}")
|
|
481
|
+
else
|
|
482
|
+
# Linux/macOSの場合
|
|
483
|
+
system("rm -rf #{path}")
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def delete_target_dir(cmd, target_dir)
|
|
471
488
|
target_dir = to_unix_path(target_dir)
|
|
472
489
|
puts "<<<<< Target dir: #{target_dir} >>>>>"
|
|
473
490
|
|
|
474
491
|
snapshots = BackupDir.scan_backup_dirs(target_dir)
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
492
|
+
if cmd == 'expire'
|
|
493
|
+
@opt.detect_expire_dirs(snapshots)
|
|
494
|
+
elsif cmd == 'delete'
|
|
495
|
+
@opt.detect_delete_dirs(snapshots, @opt.delete_from, @opt.delete_to)
|
|
496
|
+
else
|
|
497
|
+
raise RuntimeError, "unknown command: #{cmd}"
|
|
498
|
+
end
|
|
499
|
+
|
|
481
500
|
snapshots.each do |snapshot|
|
|
482
501
|
next if snapshot.keep
|
|
483
502
|
t_start = Time.now
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
if windows?
|
|
492
|
-
# Windowsの場合
|
|
493
|
-
win_backup_path = to_win_path(snapshot.path)
|
|
494
|
-
|
|
495
|
-
# byenow = "byenow"
|
|
496
|
-
# if which(byenow)
|
|
497
|
-
# print " bynow"
|
|
498
|
-
# system("byenow -y --delete-ntapi --one-liner #{snapshot.path}")
|
|
499
|
-
# else
|
|
500
|
-
# print " pass1"
|
|
501
|
-
# system("del /F /S /Q #{win_backup_path} > nul")
|
|
502
|
-
# print " pass2"
|
|
503
|
-
# system("rmdir /S /Q #{win_backup_path}")
|
|
504
|
-
# end
|
|
505
|
-
system("rmdir /S /Q #{win_backup_path}")
|
|
506
|
-
else
|
|
507
|
-
# Linux/macOSの場合
|
|
508
|
-
system("rm -rf #{snapshot.path}")
|
|
503
|
+
|
|
504
|
+
if @opt.delete_dirs.size > 0
|
|
505
|
+
#削除するディレクトリが指定されている場合日付バックアップディレクトリの下そのディレクトリを削除
|
|
506
|
+
@opt.delete_dirs.each do |delete_dir|
|
|
507
|
+
delete_path = File.join(snapshot.path, delete_dir)
|
|
508
|
+
rm_dir(delete_path)
|
|
509
509
|
end
|
|
510
|
+
else
|
|
511
|
+
#それ以外はバックアップディレクトリ全体が対象
|
|
512
|
+
rm_dir(snapshot.path)
|
|
510
513
|
end
|
|
511
514
|
|
|
512
515
|
t_end = Time.now
|
|
@@ -527,8 +530,10 @@ module Qdumpfs
|
|
|
527
530
|
puts "Keep dirs:"
|
|
528
531
|
snapshots.each do |snapshot|
|
|
529
532
|
puts snapshot.path if snapshot.keep
|
|
530
|
-
end
|
|
531
|
-
|
|
533
|
+
end
|
|
532
534
|
end
|
|
535
|
+
|
|
536
|
+
|
|
533
537
|
end
|
|
538
|
+
|
|
534
539
|
end
|
data/lib/qdumpfs/option.rb
CHANGED
|
@@ -139,12 +139,19 @@ module Qdumpfs
|
|
|
139
139
|
@keep_month = $1.to_i if keep =~ /(\d+)M/
|
|
140
140
|
@keep_week = $1.to_i if keep =~ /(\d+)W/
|
|
141
141
|
@keep_day = $1.to_i if keep =~ /(\d+)D/
|
|
142
|
+
@delete_from = @opts[:delete_from]
|
|
143
|
+
@delete_to = @opts[:delete_to]
|
|
144
|
+
@delete_dirs = @opts[:delete_dirs] || []
|
|
145
|
+
@backup_at = @opts[:backup_at]
|
|
142
146
|
@today = Date.today
|
|
147
|
+
@debug = @opts[:d]
|
|
143
148
|
end
|
|
144
149
|
attr_reader :dirs, :src, :dst, :cmd
|
|
145
150
|
attr_reader :keep_year, :keep_month, :keep_week, :keep_day
|
|
146
151
|
attr_reader :logdir, :logpath, :verifypath
|
|
147
152
|
attr_reader :logger, :matcher, :reporter, :interval_proc
|
|
153
|
+
attr_reader :delete_from, :delete_to, :delete_dirs, :backup_at
|
|
154
|
+
attr_reader :debug
|
|
148
155
|
|
|
149
156
|
def report(type, filename)
|
|
150
157
|
if @opts[:v]
|
|
@@ -162,7 +169,9 @@ module Qdumpfs
|
|
|
162
169
|
else
|
|
163
170
|
# 何も指定されていない場合
|
|
164
171
|
if type == 'new_file'
|
|
165
|
-
|
|
172
|
+
stat = File.stat(filename)
|
|
173
|
+
size = stat.size
|
|
174
|
+
msg = format_report(type, filename, size)
|
|
166
175
|
end
|
|
167
176
|
end
|
|
168
177
|
log(msg)
|
|
@@ -204,12 +213,32 @@ module Qdumpfs
|
|
|
204
213
|
end
|
|
205
214
|
end
|
|
206
215
|
|
|
207
|
-
def
|
|
216
|
+
def detect_expire_dirs(backup_dirs)
|
|
208
217
|
detect_year_keep_dirs(backup_dirs)
|
|
209
218
|
detect_month_keep_dirs(backup_dirs)
|
|
210
219
|
detect_week_keep_dirs(backup_dirs)
|
|
211
220
|
detect_day_keep_dirs(backup_dirs)
|
|
212
221
|
end
|
|
222
|
+
|
|
223
|
+
def detect_delete_dirs(backup_dirs, delete_from, delete_to)
|
|
224
|
+
|
|
225
|
+
backup_dirs.each do |backup_dir|
|
|
226
|
+
backup_dir.keep = true
|
|
227
|
+
if delete_from && delete_to
|
|
228
|
+
if backup_dir.date >= delete_from && backup_dir.date <= delete_to
|
|
229
|
+
backup_dir.keep = false
|
|
230
|
+
end
|
|
231
|
+
elsif delete_from
|
|
232
|
+
if backup_dir.date >= delete_from
|
|
233
|
+
backup_dir.keep = false
|
|
234
|
+
end
|
|
235
|
+
elsif delete_to
|
|
236
|
+
if backup_dir.date <= delete_to
|
|
237
|
+
backup_dir.keep = false
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
213
242
|
|
|
214
243
|
def open_verifyfile
|
|
215
244
|
if FileTest.file?(@verifypath)
|
|
@@ -227,8 +256,8 @@ module Qdumpfs
|
|
|
227
256
|
end
|
|
228
257
|
|
|
229
258
|
private
|
|
230
|
-
def format_report(type, filename)
|
|
231
|
-
sprintf("
|
|
259
|
+
def format_report(type, filename, size)
|
|
260
|
+
sprintf("%s\t%s\t%d\n", type, filename, size)
|
|
232
261
|
end
|
|
233
262
|
|
|
234
263
|
def format_report_with_size(type, filename, size, format_size)
|
data/lib/qdumpfs/util.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# coding: utf-8
|
|
1
2
|
def wprintf(format, *args)
|
|
2
3
|
STDERR.printf("pdumpfs: " + format + "\n", *args)
|
|
3
4
|
end
|
|
@@ -72,14 +73,14 @@ module QdumpfsFind
|
|
|
72
73
|
yield file.dup.taint
|
|
73
74
|
begin
|
|
74
75
|
s = File.lstat(file)
|
|
75
|
-
rescue
|
|
76
|
+
rescue => e
|
|
76
77
|
logger.print("File.lstat path=#{file} error=#{e.message}")
|
|
77
78
|
next
|
|
78
79
|
end
|
|
79
80
|
if s.directory? then
|
|
80
81
|
begin
|
|
81
82
|
fs = Dir.entries(file, :encoding=>'UTF-8')
|
|
82
|
-
rescue
|
|
83
|
+
rescue => e
|
|
83
84
|
logger.print("Dir.entries path=#{file} error=#{e.message}")
|
|
84
85
|
next
|
|
85
86
|
end
|
|
@@ -106,23 +107,22 @@ module QdumpfsUtils
|
|
|
106
107
|
|
|
107
108
|
# We don't use File.copy for calling @interval_proc.
|
|
108
109
|
def copy_file(src, dest)
|
|
109
|
-
|
|
110
|
-
File.open(
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
begin
|
|
111
|
+
File.open(src, 'rb') {|r|
|
|
112
|
+
File.open(dest, 'wb') {|w|
|
|
113
|
+
block_size = (r.stat.blksize or 8192)
|
|
113
114
|
i = 0
|
|
114
115
|
while true
|
|
115
116
|
block = r.sysread(block_size)
|
|
116
117
|
w.syswrite(block)
|
|
117
118
|
i += 1
|
|
118
119
|
@written_bytes += block.size
|
|
119
|
-
# @interval_proc.call if i % 10 == 0
|
|
120
120
|
end
|
|
121
|
-
|
|
122
|
-
# puts e.message, e.backtrace
|
|
123
|
-
end
|
|
121
|
+
}
|
|
124
122
|
}
|
|
125
|
-
|
|
123
|
+
rescue EOFError => e
|
|
124
|
+
# puts e.message, e.backtrace
|
|
125
|
+
end
|
|
126
126
|
unless FileTest.file?(dest)
|
|
127
127
|
raise "copy_file fails #{dest}"
|
|
128
128
|
end
|
|
@@ -278,6 +278,10 @@ module QdumpfsUtils
|
|
|
278
278
|
|
|
279
279
|
def to_unix_path(path)
|
|
280
280
|
path.gsub(/\\/, '/')
|
|
281
|
-
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def to_time(date)
|
|
284
|
+
Time.local(date.year, date.month, date.day)
|
|
285
|
+
end
|
|
282
286
|
end
|
|
283
287
|
|
data/lib/qdumpfs/version.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
module Qdumpfs
|
|
2
|
-
VERSION = "0.
|
|
3
|
-
end
|
|
1
|
+
module Qdumpfs
|
|
2
|
+
VERSION = "0.9.0"
|
|
3
|
+
end
|
|
4
|
+
|
data/run_qdumpfs.sh
CHANGED
data/sample.sh
ADDED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: qdumpfs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- src
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -57,6 +57,7 @@ email:
|
|
|
57
57
|
- src@srcw.net
|
|
58
58
|
executables:
|
|
59
59
|
- qdumpfs
|
|
60
|
+
- sample
|
|
60
61
|
extensions: []
|
|
61
62
|
extra_rdoc_files: []
|
|
62
63
|
files:
|
|
@@ -73,7 +74,10 @@ files:
|
|
|
73
74
|
- bin/setup
|
|
74
75
|
- build.cmd
|
|
75
76
|
- build.sh
|
|
77
|
+
- data/from/0.txt
|
|
78
|
+
- data/from/a/1.txt
|
|
76
79
|
- exe/qdumpfs
|
|
80
|
+
- exe/sample
|
|
77
81
|
- lib/qdumpfs.rb
|
|
78
82
|
- lib/qdumpfs/option.rb
|
|
79
83
|
- lib/qdumpfs/util.rb
|
|
@@ -85,6 +89,7 @@ files:
|
|
|
85
89
|
- run_qdumpfs.cmd
|
|
86
90
|
- run_qdumpfs.sh
|
|
87
91
|
- run_sync.cmd
|
|
92
|
+
- sample.sh
|
|
88
93
|
- test_pdumpfs/data/bar
|
|
89
94
|
- test_pdumpfs/data/baz/quux
|
|
90
95
|
- test_pdumpfs/data/file
|