file_permissions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'bundler/gem_tasks'
21
+ require 'rake'
22
+ require 'pathname'
23
+ require 'yard'
24
+ require 'rspec/core/rake_task'
25
+
26
+ RSpec::Core::RakeTask.new
27
+
28
+ YARD::Rake::YardocTask.new('doc')
29
+
30
+ desc "Removes temporary project files"
31
+ task :clean do
32
+ %w{doc/api coverage pkg .yardoc .rbx Gemfile.lock}.map{|name| Pathname.new(name) }.each do |path|
33
+ path.rmtree if path.exist?
34
+ end
35
+
36
+ Pathname.glob('*.gem').each &:delete
37
+ Pathname.glob('**/*.rbc').each &:delete
38
+ end
39
+
40
+ desc "Opens an interactive console with the project code loaded"
41
+ task :console do
42
+ Bundler.setup
43
+ require 'pry'
44
+ require 'file_permissions'
45
+ Pry.start(GodObject::FilePermissions)
46
+ end
47
+
48
+ task default: :spec
@@ -0,0 +1,67 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require File.expand_path('../lib/god_object/file_permissions/version', __FILE__)
21
+
22
+ Gem::Specification.new do |gem|
23
+ gem.name = "file_permissions"
24
+ gem.version = GodObject::FilePermissions::VERSION.dup
25
+ gem.authors = ["Oliver Feldt", "Alexander E. Fischer", "Axel Sorge", "Andreas Wurm"]
26
+ gem.email = ["of@godobject.net", "aef@godobject.net", "as@godobject.net", "aw@godobject.net"]
27
+ gem.description = <<-DESCRIPTION
28
+ FilePermissions is a Ruby library providing an object representation of the
29
+ file permission bits in POSIX systems.
30
+
31
+ It can handle the generic read, write and execute permissions, as well as
32
+ the setuid, setgid and sticky flags. Permission sets can be read from file
33
+ system objects, parsed from typical string representations or simply
34
+ defined by their numeric representation. They can then be manipulated
35
+ through binary logic operators and written back to file system objects.
36
+ DESCRIPTION
37
+ gem.summary = "Representation and manipulation of POSIX system file permissions in Ruby."
38
+ gem.homepage = "https://www.godobject.net/"
39
+ gem.license = "ISC"
40
+ gem.has_rdoc = "yard"
41
+ gem.extra_rdoc_files = ["HISTORY.md", "LICENSE.md"]
42
+ gem.rubyforge_project = nil
43
+
44
+ `git ls-files 2> /dev/null`
45
+
46
+ if $?.success?
47
+ gem.files = `git ls-files`.split($\)
48
+ else
49
+ gem.files = `ls -1`.split($\)
50
+ end
51
+
52
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
53
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
54
+ gem.require_paths = ["lib"]
55
+
56
+ gem.required_ruby_version = '>= 1.9.3'
57
+
58
+ gem.add_dependency('bit_set')
59
+
60
+ gem.add_development_dependency('rake')
61
+ gem.add_development_dependency('bundler')
62
+ gem.add_development_dependency('rspec')
63
+ gem.add_development_dependency('simplecov')
64
+ gem.add_development_dependency('pry')
65
+ gem.add_development_dependency('yard')
66
+ gem.add_development_dependency('kramdown')
67
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ # Helper file to allow loading by gem name.
21
+
22
+ require 'god_object/file_permissions'
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ require 'set'
21
+ require 'forwardable'
22
+ require 'bit_set'
23
+
24
+ # Namespace for projects of the GodObject team <dev@godobject.net>.
25
+ #
26
+ # If you want to be able to simply type Example instead of GodObject::Example
27
+ # to address classes in this namespace simply write the following before using
28
+ # the classes.
29
+ #
30
+ # @example Including the namespace
31
+ # include GodObject
32
+ # @see https://www.godobject.net/
33
+ module GodObject
34
+
35
+ # Namespace for components of the "file_permissions" library
36
+ module FilePermissions
37
+
38
+ end
39
+
40
+ end
41
+
42
+ require 'god_object/file_permissions/helper_mixin'
43
+ require 'god_object/file_permissions/version'
44
+ require 'god_object/file_permissions/exceptions'
45
+ require 'god_object/file_permissions/mode_mixin'
46
+ require 'god_object/file_permissions/mode'
47
+ require 'god_object/file_permissions/special_mode'
48
+ require 'god_object/file_permissions/complex_mode'
@@ -0,0 +1,259 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject
21
+ module FilePermissions
22
+
23
+ # An aggregate of Mode and SpecialMode to represent normal file
24
+ # permissions in a POSIX environment.
25
+ class ComplexMode
26
+
27
+ # @return [GodObject::FilePermissions::Mode] permissions for the owner
28
+ attr_accessor :user
29
+
30
+ # @return [GodObject::FilePermissions::Mode] permissions for the owning
31
+ # group
32
+ attr_accessor :group
33
+
34
+ # @return [GodObject::FilePermissions::Mode] permissions for everyone
35
+ # else
36
+ attr_accessor :other
37
+
38
+ # @return [GodObject::FilePermissions::SpecialMode] special file flags
39
+ attr_accessor :special
40
+
41
+ extend Forwardable
42
+ include HelperMixin
43
+
44
+ class << self
45
+ include HelperMixin
46
+
47
+ # @overload build(complex_mode)
48
+ # Returns an existing instance of
49
+ # GodObject::FilePermissions::ComplexMode
50
+ # @param [GodObject::FilePermissions::ComplexMode] complex_mode an
51
+ # already existing ComplexMode
52
+ # @return [GodObject::FilePermissions::ComplexMode] the same
53
+ # ComplexMode object
54
+ #
55
+ # @overload build(numeric)
56
+ # Returns a new ComplexMode object with the given numeric
57
+ # representation.
58
+ # @param [Integer] numeric a numeric representation
59
+ # @return [GodObject::FilePermissions::ComplexMode] a new ComplexMode
60
+ # object
61
+ #
62
+ # @overload build(enabled_digits)
63
+ # Returns a new ComplexMode object with the given enabled digits
64
+ # @param [Array<:user_read, :user_write, :user_execute,
65
+ # :group_read, :group_write, :group_execute, :other_read,
66
+ # :other_write, :other_execute, :setuid, :setgid, :sticky>]
67
+ # enabled_digits a list of enabled digits
68
+ # @return [GodObject::FilePermissions::ComplexMode] a new ComplexMode
69
+ # object
70
+ def build(mode)
71
+ if mode.kind_of?(self)
72
+ mode
73
+ else
74
+ new(mode)
75
+ end
76
+ end
77
+
78
+ # Creates a new complex mode from filesystem object given by path.
79
+ #
80
+ # @param [Pathname, String] path path of the source filesystem object
81
+ # @param [:resolve_symlinks, :target_symlinks] symlink_handling if set
82
+ # to :target_symlinks and the target is a symlink, the symlink will
83
+ # not be resolved but is itself used as source. By default, the
84
+ # symlink will be resolved
85
+ def from_file(path, symlink_handling = :resolve_symlinks)
86
+ file = to_pathname(path)
87
+
88
+ case symlink_handling
89
+ when :resolve_symlinks
90
+ new(file.stat.mode)
91
+ when :target_symlinks
92
+ new(file.lstat.mode)
93
+ else
94
+ raise ArgumentError, "Invalid symlink handling: #{symlink_handling.inspect}"
95
+ end
96
+ end
97
+ end
98
+
99
+ # @overload initialize(numeric)
100
+ # Returns a new ComplexMode object with the given numeric
101
+ # representation.
102
+ # @param [Integer] numeric a numeric representation
103
+ # @return [GodObject::FilePermissions::ComplexMode] a new ComplexMode
104
+ # object
105
+ #
106
+ # @overload initialize(enabled_digits)
107
+ # Returns a new ComplexMode object with the given enabled digits
108
+ # @param [Array<:user_read, :user_write, :user_execute, :group_read,
109
+ # :group_write, :group_execute, :other_read, :other_write,
110
+ # :other_execute, :setuid, :setgid, :sticky>] enabled_digits a list
111
+ # of enabled digits
112
+ # @return [GodObject::FilePermissions::ComplexMode] a new ComplexMode
113
+ # object
114
+ def initialize(*mode_components)
115
+ sub_mode_components = Hash.new{|hash, key| hash[key] = Set.new }
116
+
117
+ if mode_components.size == 1 && mode_components.first.respond_to?(:to_int)
118
+ integer = mode_components.first
119
+
120
+ [:other, :group, :user, :special].each do |mode|
121
+ sub_mode_components[mode] = integer & 0b111
122
+ integer = integer >> 3 unless mode == :special
123
+ end
124
+ else
125
+ if mode_components.size == 1 && mode_components.first.is_a?(Enumerable)
126
+ mode_components = mode_components.first
127
+ end
128
+
129
+ mode_components.flatten.each do |digit|
130
+ case digit
131
+ when /^user_(.*)$/
132
+ sub_mode_components[:user] << $1.to_sym
133
+ when /^group_(.*)$/
134
+ sub_mode_components[:group] << $1.to_sym
135
+ when /^other_(.*)$/
136
+ sub_mode_components[:other] << $1.to_sym
137
+ else
138
+ sub_mode_components[:special] << digit
139
+ end
140
+ end
141
+ end
142
+
143
+ @user = Mode.new(sub_mode_components[:user])
144
+ @group = Mode.new(sub_mode_components[:group])
145
+ @other = Mode.new(sub_mode_components[:other])
146
+ @special = SpecialMode.new(sub_mode_components[:special])
147
+ end
148
+
149
+ # Assigns the mode to a filesystem object given by path.
150
+ #
151
+ # @param [Pathname, String] path path of the target filesystem object
152
+ # @param [:resolve_symlinks, :target_symlinks] symlink_handling if set to
153
+ # :target_symlinks and the target is a symlink, the symlink will not be
154
+ # resolved but is itself used as target. By default, the symlink will
155
+ # be resolved
156
+ def assign_to_file(path, symlink_handling = :resolve_symlinks)
157
+ file = to_pathname(path)
158
+
159
+ case symlink_handling
160
+ when :resolve_symlinks
161
+ file.chmod(to_i)
162
+ when :target_symlinks
163
+ begin
164
+ file.lchmod(to_i)
165
+ rescue ::NotImplementedError, Errno::ENOSYS
166
+ raise NotImplementedError, "lchmod function is not available in current OS or Ruby environment"
167
+ end
168
+ else
169
+ raise ArgumentError, "Invalid symlink handling: #{symlink_handling.inspect}"
170
+ end
171
+ end
172
+
173
+ # Represents the ComplexMode as String for debugging.
174
+ #
175
+ # @return [String] a String representation for debugging
176
+ def inspect
177
+ "#<#{self.class}: #{to_s.inspect}>"
178
+ end
179
+
180
+ # Represents the ComplexMode as String.
181
+ #
182
+ # Uses the format used by the `ls` utility.
183
+ #
184
+ # @return [String] a String representation
185
+ def to_s
186
+ string = ''
187
+
188
+ string << case [@special.setuid?, @user.execute?]
189
+ when [true, true]
190
+ @user.to_s[0..1] << 's'
191
+ when [true, false]
192
+ @user.to_s[0..1] << 'S'
193
+ else
194
+ @user.to_s
195
+ end
196
+
197
+ string << case [@special.setgid?, @group.execute?]
198
+ when [true, true]
199
+ @group.to_s[0..1] << 's'
200
+ when [true, false]
201
+ @group.to_s[0..1] << 'S'
202
+ else
203
+ @group.to_s
204
+ end
205
+
206
+ string << case [@special.sticky?, @other.execute?]
207
+ when [true, true]
208
+ @other.to_s[0..1] << 't'
209
+ when [true, false]
210
+ @other.to_s[0..1] << 'T'
211
+ else
212
+ @other.to_s
213
+ end
214
+
215
+ string
216
+ end
217
+
218
+ # Converts the ComplexMode to a four-digit octal representation
219
+ #
220
+ # @return [Integer] four-digit octal representation
221
+ def to_i
222
+ result = 0
223
+
224
+ [@special, @user, @group, @other].each do |mode|
225
+ result = (result << 3) | mode.to_i
226
+ end
227
+
228
+ result
229
+ end
230
+
231
+ # @!method setuid
232
+ # @attribute setuid [readonly]
233
+ # @return (see GodObject::FilePermissions::SpecialMode#setuid)
234
+ #
235
+ # @!method setuid?
236
+ # @attribute setuid? [readonly]
237
+ # @return (see GodObject::FilePermissions::SpecialMode#setuid?)
238
+ #
239
+ # @!method setgid
240
+ # @attribute setgid [readonly]
241
+ # @return (see GodObject::FilePermissions::SpecialMode#setgid)
242
+ #
243
+ # @!method setgid?
244
+ # @attribute setgid? [readonly]
245
+ # @return (see GodObject::FilePermissions::SpecialMode#setgid?)
246
+ #
247
+ # @!method sticky
248
+ # @attribute sticky [readonly]
249
+ # @return (see GodObject::FilePermissions::SpecialMode#sticky)
250
+ #
251
+ # @!method sticky?
252
+ # @attribute sticky? [readonly]
253
+ # @return (see GodObject::FilePermissions::SpecialMode#sticky?)
254
+ def_delegators :@special, :setuid?, :setgid?, :sticky?
255
+
256
+ end
257
+
258
+ end
259
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+ Copyright GodObject Team <dev@godobject.net>, 2012-2016
4
+
5
+ This file is part of FilePermissions.
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
13
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ =end
19
+
20
+ module GodObject
21
+ module FilePermissions
22
+
23
+ # Base class for exceptions specific to GodObject::FilePermissions.
24
+ class Error < StandardError; end
25
+
26
+ # An error while parsing a String representation.
27
+ class ParserError < Error; end
28
+
29
+ # An error which is raised in situations where lchmod is unavailable.
30
+ class NotImplementedError < Error; end
31
+
32
+ end
33
+ end