libacl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +66 -0
  2. data/lib/libacl.rb +387 -0
  3. metadata +75 -0
data/README ADDED
@@ -0,0 +1,66 @@
1
+ An implementation of linux ACL (posix1e).
2
+ Provides more convenience than ruby-acl, and uses FFI so it requires no
3
+ extra compilation of c files, and works with jruby.
4
+
5
+
6
+ first install ffi/nice-ffi:
7
+ gem install ffi nice-ffi
8
+
9
+ Then download the file 'acl-ffi.rb' and load it:
10
+ require 'acl-ffi.rb'
11
+
12
+ Usage example:
13
+ require 'acl-ffi.rb'
14
+ require 'test/unit/assertions'
15
+ include Test::Unit::Assertions
16
+ require 'fileutils'
17
+ include FileUtils
18
+
19
+ acl= LibACL::ACL.from_text 'user::rwx
20
+ group::rx
21
+ other::---
22
+ mask::rwx
23
+ user:root:rwx
24
+ group:daemon:rx'
25
+ assert acl.valid?
26
+
27
+
28
+ acl_invalid= LibACL::ACL.from_text '
29
+ user:nonexiestent_user:---
30
+ group:does_not_exist:rx
31
+ garbage_entry:user:::*:xyz'
32
+ assert !acl_invalid.valid?
33
+
34
+
35
+ #You can write ACL's to and read from directories and files
36
+ touch '/tmp/foo'
37
+ mkdir '/tmp/dir' unless File.exist? '/tmp/dir'
38
+
39
+ acl.set_file '/tmp/foo'
40
+ acl.set_default '/tmp/dir'
41
+
42
+ acl_foo = LibACL::ACL.from_file '/tmp/foo'
43
+ acl_def = LibACL::ACL.default '/tmp/dir'
44
+
45
+ assert_equal acl_foo.to_text, acl.to_text
46
+ assert_equal acl_def.to_text, acl.to_text
47
+
48
+
49
+ #Operate on each entry
50
+ p "Each entry in acl_foo:"
51
+ acl_foo.each do |entry|
52
+ puts entry
53
+ end
54
+
55
+
56
+ #You can query the acl and get a text representation
57
+ assert_equal acl_foo.user_obj.permset.to_s, 'rwx'
58
+ assert_equal acl_foo.other.permset.to_s, "---"
59
+
60
+
61
+ #Find works as expected, and convenience methods exist
62
+ found = acl_foo.find do |entry|
63
+ entry.tag_type == :mask
64
+ end
65
+
66
+ assert found == acl_foo.mask
@@ -0,0 +1,387 @@
1
+ require 'rubygems'
2
+ gem 'ffi', '>= 0.5.0'
3
+ require 'ffi'
4
+ require 'nice-ffi'
5
+ require 'test/unit/assertions'
6
+ include Test::Unit::Assertions
7
+
8
+ #Types:
9
+ #
10
+ #typedef unsigned int acl_type_t;
11
+ #typedef int acl_tag_t;
12
+ #typedef unsigned int acl_perm_t;
13
+ #
14
+ #typedef struct __acl_ext *acl_t;
15
+ #typedef struct __acl_entry_ext *acl_entry_t;
16
+ #typedef struct __acl_permset_ext *acl_permset_t;
17
+
18
+
19
+ #FFI Posix ACL tested on linux and definitely not working on darwin.
20
+ module LibACL
21
+ extend NiceFFI::Library
22
+ #ffi_lib 'libacl'
23
+
24
+
25
+ if FFI::Platform::IS_LINUX
26
+ ffi_lib 'libacl'
27
+
28
+ # === Constants ===
29
+ #23.2.2 acl_perm_t values
30
+ enum :acl_perm, [
31
+ :read, 0x04,
32
+ :write, 0x02,
33
+ :execute, 0x01]
34
+
35
+
36
+ #23.2.5 acl_tag_t values
37
+ enum :acl_tag, [
38
+ :undefined_tag, 0x00,
39
+ :user_obj, 0x01, #regular owner
40
+ :user, 0x02,
41
+ :group_obj, 0x04,
42
+ :group, 0x08,
43
+ :mask, 0x10,
44
+ :other, 0x20]
45
+
46
+
47
+
48
+ #23.3.6 acl_type_t values */
49
+ enum :acl_type, [
50
+ :access, 0x8000,
51
+ :default, 0x4000]
52
+
53
+
54
+ #23.2.7 ACL qualifier constants */
55
+ #type :id_t
56
+ ACL_UNDEFINED_ID = -1
57
+
58
+
59
+ #23.2.8 ACL Entry Constants */
60
+ enum :acl_entry, [
61
+ :first_entry,0,
62
+ :next_entry,1]
63
+
64
+ end #is linux
65
+
66
+
67
+
68
+ class ACL < NiceFFI::OpaqueStruct
69
+ include Enumerable
70
+ #Create struct capable of holding num entries
71
+ def self.init(num=10)
72
+ LibACL::acl_init(num)
73
+ end
74
+
75
+ def self.release(ptr)
76
+ acl_free(ptr)
77
+ end
78
+
79
+ #Construct from file, using mode :access or :default
80
+ def self.from_file(path, mode=:access)
81
+ LibACL::acl_get_file(path,mode)
82
+ end
83
+
84
+ def self.default(dir)
85
+ assert File.directory? dir
86
+ self.from_file(dir,:default)
87
+ end
88
+
89
+ #Construct from text
90
+ def self.from_text(text)
91
+ LibACL::acl_from_text(text)
92
+ end
93
+
94
+ #Create a copy of acl.
95
+ def clone
96
+ LibACL::acl_dup(self)
97
+ end
98
+
99
+ def valid?
100
+ LibACL::acl_valid(self)==0
101
+ end
102
+
103
+
104
+ def to_text
105
+ LibACL::acl_to_text(self, nil)
106
+ end
107
+
108
+
109
+ def set_file(path, mode=:access)
110
+ assert valid?
111
+ assert File.exists? path
112
+ LibACL::acl_set_file(path, mode, self)
113
+ end
114
+
115
+
116
+ def set_default(dir)
117
+ assert valid?
118
+ assert File.directory? dir
119
+ set_file(dir, :default)
120
+ end
121
+
122
+
123
+ def create_entry
124
+ entry_p = FFI::MemoryPointer.new :pointer
125
+ #acl_p = self.pointer
126
+ ret= LibACL::acl_create_entry(self, entry_p )
127
+ raise "Can't create entry" if ret == -1
128
+
129
+
130
+ #test this case...
131
+ # #in case of reallocation
132
+ # if acl_p.pointer.address != self.pointer.address
133
+ # self.pointer=acl_p
134
+ # end
135
+ Entry.new entry_p.read_pointer
136
+ end
137
+
138
+ #I'm unsure of how memory is handled in this case
139
+ #Test!
140
+ def delete_entry(entry)
141
+ ret = LibACL::acl_delete_entry(self,entry)
142
+ raise "Can't delete #{entry}" if ret == -1
143
+ end
144
+
145
+
146
+ def each(&blk)
147
+ ptr = FFI::MemoryPointer.new :pointer
148
+ having = LibACL::acl_get_entry(self, :first_entry, ptr)
149
+ while (having>0)
150
+ entry=Entry.new ptr.read_pointer
151
+ blk.call entry
152
+ having = LibACL::acl_get_entry(self, :next_entry, ptr)
153
+ end
154
+
155
+ raise "Error getting entry" if having == -1
156
+ end
157
+
158
+ #methods using each implementation
159
+
160
+ def user_obj
161
+ entry_find :user_obj
162
+ end
163
+
164
+ def group_obj
165
+ entry_find :group_obj
166
+ end
167
+
168
+ def other
169
+ entry_find :other
170
+ end
171
+
172
+ def mask
173
+ entry_find :mask
174
+ end
175
+
176
+
177
+ def entry_find(tag)
178
+ find do |entry|
179
+ entry.tag_type==tag
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+
186
+
187
+ class Entry < NiceFFI::OpaqueStruct
188
+ def self.release(ptr)
189
+ acl_free(ptr)
190
+ end
191
+
192
+ #replace this entry with source
193
+ def replace(source)
194
+ LibACL::acl_copy_entry(self,source)
195
+ end
196
+
197
+
198
+ def permset
199
+ ptr = FFI::MemoryPointer.new :pointer
200
+ ret = LibACL::acl_get_permset(self, ptr)
201
+ raise "Error" if ret!=0
202
+ Permset.new ptr.read_pointer
203
+ end
204
+
205
+ #def permset=
206
+ #
207
+ #end
208
+
209
+ def tag_type
210
+ type= LibACL::find_type(:acl_tag)
211
+ ptr = FFI::MemoryPointer.new type
212
+ ret = LibACL::acl_get_tag_type(self, ptr)
213
+ raise "Error" if ret !=0
214
+ type[ptr.read_int]
215
+ end
216
+
217
+ def qualifier
218
+ ptr = LibACL::acl_get_qualifier(self)
219
+ if ptr.null?
220
+ return nil
221
+ else
222
+ return ptr.read_int
223
+ end
224
+ end
225
+
226
+ def == (other)
227
+ permset == other.permset and
228
+ tag_type == other.tag_type and
229
+ qualifier == other.qualifier
230
+ end
231
+
232
+ def to_s
233
+ # tag=tag_type.to_s.sub("_obj","")
234
+ "#{tag_type}:#{qualifier}:#{permset}"
235
+ end
236
+
237
+ end
238
+
239
+ class Permset<NiceFFI::OpaqueStruct
240
+ @@perm_t=LibACL::find_type(:acl_perm)
241
+
242
+ def clear
243
+ LibACL::acl_clear_perms(self)
244
+ end
245
+
246
+ def add(perm)
247
+ LibACL::acl_add_perm(self,@@perm_t[perm])
248
+ end
249
+
250
+ def delete(perm)
251
+ LibACL::acl_delete_perm(self,@@perm_t[perm])
252
+ end
253
+
254
+ def is_set?(perm)
255
+ LibACL::acl_get_perm(self, @@perm_t[perm]) >0
256
+ end
257
+
258
+ #a linux hack/shortcut
259
+ def to_i
260
+ pointer.read_int
261
+ end
262
+
263
+ def == (other)
264
+ to_i == other.to_i
265
+ end
266
+
267
+
268
+ def read?
269
+ is_set? :read
270
+ end
271
+
272
+ def write?
273
+ is_set? :write
274
+ end
275
+
276
+ def execute?
277
+ is_set? :execute
278
+ end
279
+
280
+ def to_s
281
+ ret=""
282
+ read? ? ret << "r" : ret << "-"
283
+ write? ? ret << "w" : ret << "-"
284
+ execute? ? ret << "x" : ret << "-"
285
+ ret
286
+ end
287
+
288
+ end
289
+
290
+
291
+
292
+
293
+
294
+ #=== ACL manipulation ===
295
+
296
+ #arg: entries_nr to allocate
297
+ attach_function 'acl_init',[:int],NiceFFI::TypedPointer( ACL )
298
+ attach_function 'acl_dup', [:pointer],NiceFFI::TypedPointer( ACL )
299
+ attach_function 'acl_free', [:pointer],:void
300
+ attach_function 'acl_valid', [:pointer],:int
301
+
302
+
303
+ #=== Entry manipulation ===
304
+
305
+ #copy (dest, source): code
306
+ attach_function 'acl_copy_entry',[:pointer, :pointer],:int
307
+
308
+ #acl, entry*: code
309
+ attach_function 'acl_create_entry',[:pointer, :pointer],:int
310
+ attach_function 'acl_delete_entry',[:pointer, :pointer],:int
311
+
312
+ #*acl, entry_id, *entry_p: having code
313
+ attach_function 'acl_get_entry', [:pointer, :int, :pointer], :int
314
+
315
+ #Manipulate ACL entry permissions */
316
+
317
+ # extern int acl_add_perm(acl_permset_t permset_d, acl_perm_t perm);
318
+ attach_function 'acl_add_perm',[:pointer,:acl_perm],:int
319
+
320
+ # extern int acl_calc_mask(acl_t *acl_p);
321
+ # extern int acl_clear_perms(acl_permset_t permset_d);
322
+ attach_function 'acl_clear_perms',[:pointer],:int
323
+
324
+ # extern int acl_delete_perm(acl_permset_t permset_d, acl_perm_t perm);
325
+ attach_function 'acl_delete_perm',[:pointer, :acl_perm],:int
326
+
327
+ # extern int acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p);
328
+ attach_function 'acl_get_permset', [:pointer,:pointer],:int
329
+ # extern int acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d);
330
+
331
+
332
+ #on linux
333
+ if FFI::Platform::IS_LINUX
334
+ attach_function 'acl_get_perm',[:pointer,:acl_perm],:int
335
+ elsif FFI::Platform::IS_BSD
336
+ attach_function 'acl_get_perm',:acl_get_perm_np,[:pointer,:acl_perm],:int
337
+ end
338
+ #on bsd/osx
339
+ #attach_function 'acl_get_perm_np',[:pointer,:pointer],:int
340
+
341
+
342
+ # #Manipulate ACL entry tag type and qualifier */
343
+ # extern void * acl_get_qualifier(acl_entry_t entry_d);
344
+ attach_function 'acl_get_qualifier',[:pointer],:pointer
345
+ # extern int acl_get_tag_type(acl_entry_t entry_d, acl_tag_t *tag_type_p);
346
+ attach_function 'acl_get_tag_type',[:pointer,:pointer],:int
347
+ # extern int acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p);
348
+ attach_function 'acl_set_qualifier',[:pointer,:pointer],:int
349
+ # extern int acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type);
350
+
351
+
352
+
353
+ #=== Format translation ===
354
+
355
+ #attach_function 'acl_copy_ext', [:inbuffer,:pointer,:ssize_t],:ssize_t
356
+ #extern acl_t acl_copy_int(const void *buf_p);
357
+
358
+ attach_function 'acl_from_text', [:string],NiceFFI::TypedPointer( ACL )
359
+ attach_function 'acl_size',[:pointer],:ssize_t
360
+
361
+ #second pointer is ssize_t *len_p
362
+ attach_function 'acl_to_text',[:pointer,:pointer],:string
363
+
364
+ #=== Object manipulation ===
365
+
366
+ #extern int acl_delete_def_file(const char *path_p);
367
+ #extern acl_t acl_get_fd(int fd);
368
+
369
+ #path, type: new acl
370
+ attach_function 'acl_get_file',[:string, :acl_type ],NiceFFI::TypedPointer( ACL )
371
+
372
+ #extern int acl_set_fd(int fd, acl_t acl);
373
+
374
+ #int acl_set_file(const char *path_p, acl_type_t type, acl_t acl);
375
+ attach_function 'acl_set_file',[:string, :acl_type, :pointer],:int
376
+
377
+
378
+ end
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+
387
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libacl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Zachris Trolin
8
+ autorequire: libacl
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-01 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ffi
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: nice-ffi
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: zachris.trolin@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ files:
44
+ - lib/libacl.rb
45
+ - README
46
+ has_rdoc: true
47
+ homepage: http://github.com/zachris/acl-ffi
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Linux ACL for ruby using ffi
74
+ test_files: []
75
+