lnbackup 2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ class FreeSpaceCalc
2
+ def initialize( path, free_files=0, free_blocks=10, log=nil )
3
+ @log = log
4
+ @stat = FileSystem.stat(path)
5
+
6
+ if (free_blocks.class == String) and (free_blocks =~ /^(\d+)%$/)
7
+ free_blocks = @stat.blocks * $1.to_i / 100
8
+ else
9
+ free_blocks = free_blocks.to_i rescue 100
10
+ end
11
+ # vzdy nechame alespon 100 volnych bloku (typicky blok=4kB)
12
+ @free_blocks = free_blocks < 100 ? 100 : free_blocks
13
+
14
+ if (free_files.class == String) and (free_files =~ /^(\d+)%$/)
15
+ free_files = @stat.files * $1.to_i / 100
16
+ else
17
+ free_files = free_files.to_i rescue 100
18
+ end
19
+ # vzdy nechame alespon 100 volnych inodu (pokud dojdou, fs se umi prekne
20
+ # podelat a ani fsck z toho nema radost)
21
+ @free_files = free_files < 100 ? 100 : free_files
22
+ end
23
+
24
+ def much_used?
25
+ @stat = FileSystem.stat(@stat.path)
26
+ if Process.euid == 0
27
+ if (@stat.blocks_free < @free_blocks) or (@stat.files_free < @free_files)
28
+ @log.debug { "FreeSpaceCalc: much used (euid=#{Process.euid}) (#{@stat.blocks_free} < #{@free_blocks}) or (#{@stat.files_free} < #{@free_files})" }
29
+ return true
30
+ end
31
+ else
32
+ if (@stat.blocks_avail < @free_blocks) or (@stat.files_avail < @free_files)
33
+ @log.debug { "FreeSpaceCalc: much used (euid=#{Process.euid}) (#{@stat.blocks_avail} < #{@free_blocks}) or (#{@stat.files_avail} < #{@free_files})" }
34
+ return true
35
+ end
36
+ end
37
+ return false
38
+ end
39
+
40
+ def get_free
41
+ @stat = FileSystem.stat(@stat.path)
42
+ return [ @stat.blocks_free, @stat.files_free ]
43
+ end
44
+
45
+ def can_backup?( path )
46
+ begin
47
+ @stat = FileSystem.stat(@stat.path)
48
+ if Process.euid == 0
49
+ if (@stat.blocks_free < @free_blocks) or (@stat.files_free < @free_files) or
50
+ (File.size(path) >= ( @stat.block_size * (@stat.blocks_free-@free_blocks) ))
51
+
52
+ @log.debug { "FreeSpaceCalc: (euid=#{Process.euid}) can't backup #{path} size #{File.size(path)}" }
53
+ @log.debug { "FreeSpaceCalc: blocks avail: #{@stat.blocks_free} should have: #{@free_blocks}" }
54
+ @log.debug { "FreeSpaceCalc: files avail: #{@stat.files_free} should have: #{@free_files}" }
55
+ return false
56
+ end
57
+ else
58
+ if (@stat.blocks_avail < @free_blocks) or (@stat.files_avail < @free_files) or
59
+ (File.size(path) >= ( @stat.block_size * (@stat.blocks_avail-@free_blocks) ))
60
+
61
+ @log.debug { "FreeSpaceCalc: (euid=#{Process.euid}) can't backup #{path} size #{File.size(path)}" }
62
+ @log.debug { "FreeSpaceCalc: blocks avail: #{@stat.blocks_avail} should have: #{@free_blocks}" }
63
+ @log.debug { "FreeSpaceCalc: files avail: #{@stat.files_avail} should have: #{@free_files}" }
64
+ return false
65
+ end
66
+ end
67
+ return true
68
+ rescue Errno::ENOENT # pokud soubor, ktery kontrolujeme prestal existovat,
69
+ # podminka je trivialne splnena
70
+ return true
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,123 @@
1
+ class File
2
+ TOO_BIG = 1024 * 1024 * 2 # 2MB
3
+
4
+ # a variant of syscopy, that propagates exception Errno::ENOSPC
5
+ # and handles some extra error states
6
+ #
7
+ def File.syscopy2 from, to
8
+ fsize = size(from)
9
+ fsize = 1024 if fsize < 512
10
+ fsize = TOO_BIG if fsize > TOO_BIG
11
+ fmode = stat(from).mode
12
+ tpath = to
13
+ not_exist = !exist?(tpath)
14
+ begin
15
+ from = open(from, "r")
16
+ from.binmode
17
+ to = open(to, "w")
18
+ to.binmode
19
+
20
+ while true
21
+ r = from.sysread(fsize)
22
+ rsize = r.size
23
+ w = 0
24
+ while w < rsize
25
+ t = to.syswrite(r[w, rsize - w])
26
+ w += t
27
+ end
28
+ end
29
+ rescue EOFError
30
+ ret = true
31
+ rescue Errno::ENOSPC
32
+ raise
33
+ rescue
34
+ ret = false
35
+ ensure
36
+ begin; to.close; rescue; end
37
+ begin; from.close; rescue; end
38
+ end
39
+ chmod(fmode, tpath) if not_exist
40
+ ret
41
+ end
42
+ end
43
+
44
+ class Hash
45
+ # "aktualizace" hashe jinou hashi: existujici klice jsou prepsany,
46
+ # neexistujici pridany a to cele rekurzivne po hashich
47
+ def append( hash )
48
+ hash.each_pair do |k,v|
49
+ if self.has_key?(k)
50
+ case v
51
+ when Hash
52
+ self[k].append(v)
53
+ else
54
+ self[k] = v
55
+ end
56
+ else
57
+ self[k] = v
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ class SysCopyFailure < StandardError
64
+ end
65
+
66
+ class MakeSpaceFailure < StandardError
67
+ attr_accessor :code
68
+ def initialize(code)
69
+ @code = code
70
+ super
71
+ end
72
+ end
73
+
74
+ class Date
75
+ # formatovani data do cesty pro zalohu
76
+ def backup_dir(hourly)
77
+ if hourly
78
+ "%d/%02d/%02d-%02d" % [year, month, day, Time.now.hour]
79
+ else
80
+ "%d/%02d/%02d" % [year, month, day]
81
+ end
82
+ end
83
+ end
84
+
85
+ module Find
86
+ #
87
+ # reimplementace funkce "find" s osetrenim vyjimky Errno::EOVERFLOW, ktera minimalne
88
+ # na ruby1.6 nastava pri zachazeni (napr. stat) se souborem o velikosti >2GB
89
+ #
90
+ # pruchod je udelan pomoci zasobniku s hloubkou, aby bylo mozne usetrit pamet
91
+ #
92
+ def Find.find3(*path)
93
+ path.collect!{|d| [d.dup,0]}
94
+ while temp = path.shift
95
+ catch(:prune) do
96
+ (file, depth) = temp
97
+ yield [file, depth]
98
+ begin
99
+ if File.lstat(file).directory? then
100
+ d = Dir.open(file)
101
+ begin
102
+ for f in d
103
+ next if f == "." or f == ".."
104
+ if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then
105
+ f = file + f
106
+ elsif file == "/" then
107
+ f = "/" + f
108
+ else
109
+ f = File.join(file, f)
110
+ end
111
+ path.unshift [f, depth+1]
112
+ end
113
+ ensure
114
+ d.close
115
+ end
116
+ end
117
+ rescue Errno::ENOENT, Errno::EACCES, Errno::EOVERFLOW
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,3 @@
1
+ module LnBackup
2
+ VERSION=2.1
3
+ end
data/lib/lnbackup.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'lnbackup/backup.rb'
2
+ require 'lnbackup/freespace.rb'
3
+ require 'lnbackup/util.rb'
4
+ require 'lnbackup/version.rb'
5
+
6
+ require 'find'
7
+ require 'date'
8
+ #require 'ftools'
9
+ require 'fileutils'
10
+ begin
11
+ require 'filesystem'
12
+ rescue LoadError
13
+ require 'sys/filesystem'
14
+ include Sys
15
+ FileSystem = Filesystem
16
+ end
17
+
18
+
19
+ require 'logger'
20
+ require 'time'
21
+
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lnbackup
3
+ version: !ruby/object:Gem::Version
4
+ version: '2.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Martin Povolny
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! "\nLnbackup is a hardlink backup system for hard drives. \n\nLnbackup
15
+ operates in a way similar to the '--link-dest' switch in rsync.\n\nIt creates incremental
16
+ backups using hardlinks so that each backup seems like a full backup. Additionaly
17
+ it can make (using hardlinks) bootable mirror from the latest backup.\n\nObviously
18
+ the target filesystem of lnbackup needs to support hardlinks.\n\nIt's run on ~200
19
+ servers for several years and it is considered stable.\n\nRead the man page for
20
+ more information."
21
+ email: martin.povolny@gmail.com
22
+ executables: []
23
+ extensions: []
24
+ extra_rdoc_files: []
25
+ files:
26
+ - lib/lnbackup.rb
27
+ - lib/lnbackup/version.rb
28
+ - lib/lnbackup/freespace.rb
29
+ - lib/lnbackup/backup.rb
30
+ - lib/lnbackup/util.rb
31
+ - bin/lnbackup
32
+ - bin/lnumount
33
+ - bin/lnmount
34
+ - bin/lnstat
35
+ - bin/pc_backup
36
+ - bin/sql_backup.sh
37
+ homepage: https://github.com/martinpovolny/lnbackup
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options:
41
+ - --title
42
+ - Lnbackup -- hardlink backup system for hard drives.
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.24
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Hardlink backup system for hard drives.
63
+ test_files: []