libacl 0.0.1

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.
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
+