qdumpfs 0.5.1 → 1.0.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 +93 -82
- data/lib/qdumpfs/option.rb +28 -1
- data/lib/qdumpfs/util.rb +16 -12
- data/lib/qdumpfs/version.rb +4 -3
- data/run_list.sh +5 -0
- data/run_qdumpfs.sh +1 -1
- data/sample.sh +5 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4f23500798845b355c0218ddb9fe5245d18bc0fb206a948d272f379adba6f3e
|
4
|
+
data.tar.gz: 1acc58713bd896da322648ac909bbbbd8359831c530e5f160d022d8091fa4adc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e1d6c3155d669e9a17a199b8ea70749615fe116c496c166bc477036c66715814337d1cbb8db562236d5bed755ba3f21bc45600f5d5e2f070f5eb847f9275057
|
7
|
+
data.tar.gz: 2a4deb71d95507c1ddba720899528874df09f0245b9a668a90aca5fd2d4d06472632ee2b5b1b7c78c1a6d5e894c4c77f21ffa09b1734350f2aff697568aede4c
|
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
|
|
@@ -120,11 +137,17 @@ module Qdumpfs
|
|
120
137
|
end
|
121
138
|
|
122
139
|
def filecount(dir)
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
result =
|
140
|
+
result = '0'
|
141
|
+
if windows?
|
142
|
+
pscmd = 'Get-ChildItem -Recurse -File | Measure-Object | %{$_.Count}'
|
143
|
+
cmd = "powershell -Command \"#{pscmd}\""
|
144
|
+
result = nil
|
145
|
+
Dir.chdir(dir) do
|
146
|
+
result = `#{cmd}`
|
147
|
+
result.chomp!
|
148
|
+
end
|
149
|
+
else
|
150
|
+
result = `find #{dir} | wc -l`
|
128
151
|
result.chomp!
|
129
152
|
end
|
130
153
|
result.to_i
|
@@ -136,29 +159,6 @@ module Qdumpfs
|
|
136
159
|
return src_count, dst_count
|
137
160
|
end
|
138
161
|
|
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
162
|
def update_snapshot(src, latest, today)
|
163
163
|
# バックアップの差分コピーを実行
|
164
164
|
# src: コピー元ディレクトリ ex) i:/from/home
|
@@ -179,7 +179,7 @@ module Qdumpfs
|
|
179
179
|
# ファイルのアップデート
|
180
180
|
update_file(s, l, t)
|
181
181
|
dirs[t] = File.stat(s) if File.ftype(s) == "directory"
|
182
|
-
rescue
|
182
|
+
rescue => e
|
183
183
|
wprintf("%s: %s", src, e.message)
|
184
184
|
next
|
185
185
|
end
|
@@ -214,7 +214,7 @@ module Qdumpfs
|
|
214
214
|
end
|
215
215
|
chown_if_root(type, s, t)
|
216
216
|
dirs[t] = File.stat(s) if File.ftype(s) == "directory"
|
217
|
-
rescue
|
217
|
+
rescue => e
|
218
218
|
wprintf("%s: %s", s, e.message)
|
219
219
|
next
|
220
220
|
end
|
@@ -227,7 +227,7 @@ module Qdumpfs
|
|
227
227
|
|
228
228
|
#コピー元のスナップショット
|
229
229
|
src_snapshots = BackupDir.scan_backup_dirs(src)
|
230
|
-
@opt.
|
230
|
+
@opt.detect_expire_dirs(src_snapshots)
|
231
231
|
|
232
232
|
# コピー先の最新スナップショット
|
233
233
|
dst_snapshots = BackupDir.scan_backup_dirs(dst)
|
@@ -296,6 +296,9 @@ module Qdumpfs
|
|
296
296
|
|
297
297
|
@written_bytes = 0
|
298
298
|
start_time = Time.now
|
299
|
+
if @opt.backup_at
|
300
|
+
start_time = to_time(@opt.backup_at)
|
301
|
+
end
|
299
302
|
src = @opt.src
|
300
303
|
dst = @opt.dst
|
301
304
|
|
@@ -439,74 +442,80 @@ module Qdumpfs
|
|
439
442
|
file.close
|
440
443
|
end
|
441
444
|
|
442
|
-
def
|
445
|
+
def delete(cmd)
|
443
446
|
@opt.validate_directories(1)
|
444
|
-
|
445
447
|
start_time = Time.now
|
446
448
|
limit_time = start_time + (@opt.limit_sec)
|
447
|
-
log("#####
|
448
|
-
|
449
|
+
log("##### #{cmd} delete-from=#{@opt.delete_from} delete-to=#{@opt.delete_to} start #{fmt(start_time)} => limit_time=#{fmt(limit_time)} #####")
|
449
450
|
@opt.dirs.each do |target_dir|
|
450
451
|
|
451
452
|
target_start = Time.now
|
452
|
-
|
453
|
+
delete_target_dir(cmd, target_dir)
|
453
454
|
target_end = Time.now
|
454
455
|
|
455
456
|
# 次回expireにかかる時間を最終expire時間の半分と予想
|
456
457
|
next_expire = (target_end - target_start) / 2
|
457
458
|
|
458
459
|
cur_time = Time.now
|
459
|
-
|
460
|
+
in_limit = (cur_time + next_expire) < limit_time
|
460
461
|
|
461
462
|
log("## cur_time=#{fmt(cur_time)} + next_expire=#{next_expire} < limit_time=#{fmt(limit_time)} in_limit=#{in_limit} ## ")
|
462
463
|
unless in_limit
|
463
464
|
break
|
464
465
|
end
|
465
466
|
end
|
466
|
-
|
467
|
-
log("##### expire end #####")
|
467
|
+
log("##### #{cmd} end #####")
|
468
468
|
end
|
469
|
-
|
470
|
-
def
|
469
|
+
|
470
|
+
def rm_dir(path)
|
471
|
+
can_delete = true
|
472
|
+
if @opt.dry_run
|
473
|
+
can_delete = false
|
474
|
+
elsif !FileTest.directory?(path)
|
475
|
+
can_delete = false
|
476
|
+
end
|
477
|
+
msg = can_delete ? "...ok..." : "...ng..."
|
478
|
+
print "Deleting #{path} #{msg}"
|
479
|
+
|
480
|
+
return unless can_delete
|
481
|
+
|
482
|
+
#それ以外は日付バックアップディレクトリ全体を削除
|
483
|
+
if windows?
|
484
|
+
# Windowsの場合
|
485
|
+
win_backup_path = to_win_path(path)
|
486
|
+
system("rmdir /S /Q #{win_backup_path}")
|
487
|
+
else
|
488
|
+
# Linux/macOSの場合
|
489
|
+
system("rm -rf #{path}")
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def delete_target_dir(cmd, target_dir)
|
471
494
|
target_dir = to_unix_path(target_dir)
|
472
495
|
puts "<<<<< Target dir: #{target_dir} >>>>>"
|
473
496
|
|
474
497
|
snapshots = BackupDir.scan_backup_dirs(target_dir)
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
498
|
+
if cmd == 'expire'
|
499
|
+
@opt.detect_expire_dirs(snapshots)
|
500
|
+
elsif cmd == 'delete'
|
501
|
+
@opt.detect_delete_dirs(snapshots, @opt.delete_from, @opt.delete_to)
|
502
|
+
else
|
503
|
+
raise RuntimeError, "unknown command: #{cmd}"
|
504
|
+
end
|
505
|
+
|
481
506
|
snapshots.each do |snapshot|
|
482
507
|
next if snapshot.keep
|
483
508
|
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}")
|
509
|
+
|
510
|
+
if @opt.delete_dirs.size > 0
|
511
|
+
#削除するディレクトリが指定されている場合日付バックアップディレクトリの下そのディレクトリを削除
|
512
|
+
@opt.delete_dirs.each do |delete_dir|
|
513
|
+
delete_path = File.join(snapshot.path, delete_dir)
|
514
|
+
rm_dir(delete_path)
|
509
515
|
end
|
516
|
+
else
|
517
|
+
#それ以外はバックアップディレクトリ全体が対象
|
518
|
+
rm_dir(snapshot.path)
|
510
519
|
end
|
511
520
|
|
512
521
|
t_end = Time.now
|
@@ -527,8 +536,10 @@ module Qdumpfs
|
|
527
536
|
puts "Keep dirs:"
|
528
537
|
snapshots.each do |snapshot|
|
529
538
|
puts snapshot.path if snapshot.keep
|
530
|
-
end
|
531
|
-
|
539
|
+
end
|
532
540
|
end
|
541
|
+
|
542
|
+
|
533
543
|
end
|
544
|
+
|
534
545
|
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]
|
@@ -206,12 +213,32 @@ module Qdumpfs
|
|
206
213
|
end
|
207
214
|
end
|
208
215
|
|
209
|
-
def
|
216
|
+
def detect_expire_dirs(backup_dirs)
|
210
217
|
detect_year_keep_dirs(backup_dirs)
|
211
218
|
detect_month_keep_dirs(backup_dirs)
|
212
219
|
detect_week_keep_dirs(backup_dirs)
|
213
220
|
detect_day_keep_dirs(backup_dirs)
|
214
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
|
215
242
|
|
216
243
|
def open_verifyfile
|
217
244
|
if FileTest.file?(@verifypath)
|
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 = "1.0.0"
|
3
|
+
end
|
4
|
+
|
data/run_list.sh
ADDED
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: 1.0.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-04-07 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
|
@@ -82,9 +86,11 @@ files:
|
|
82
86
|
- qdumpfs.gemspec
|
83
87
|
- run2_qdumpfs.cmd
|
84
88
|
- run_list.cmd
|
89
|
+
- run_list.sh
|
85
90
|
- run_qdumpfs.cmd
|
86
91
|
- run_qdumpfs.sh
|
87
92
|
- run_sync.cmd
|
93
|
+
- sample.sh
|
88
94
|
- test_pdumpfs/data/bar
|
89
95
|
- test_pdumpfs/data/baz/quux
|
90
96
|
- test_pdumpfs/data/file
|