acl 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.
@@ -0,0 +1,86 @@
1
+ require "acl"
2
+ require "test/unit"
3
+ require "fileutils"
4
+
5
+ class ACLTest < Test::Unit::TestCase
6
+ TEST_PATH='/tmp/rtest'
7
+
8
+ def test_constructors
9
+ assert_instance_of( ACL, ACL.from_file(TEST_PATH) )
10
+ assert_instance_of( ACL, ACL.default(TEST_PATH) )
11
+
12
+ assert_instance_of( ACL, ACL.new ) # new acl
13
+ assert_instance_of( ACL, a = ACL.new(10) ) # new acl with given numof entries
14
+ assert_instance_of( ACL, b = ACL.new(a) ) # duplicate given acl
15
+
16
+ assert_equal( a.to_text, b.to_text )
17
+ end
18
+
19
+ def test_to_from_text
20
+ a = ACL.default(TEST_PATH)
21
+ assert_instance_of( String, a.to_text ) # test if to_text gives String
22
+
23
+ b = ACL.from_text( a.to_text ) # create new acl from string
24
+ assert_instance_of( ACL, b ) # must by class ACL
25
+
26
+ assert_equal( a.to_text, b.to_text ) # text reprezentation of both acl's must be the same
27
+ end
28
+
29
+ def test_entry
30
+ entry = nil
31
+ a = ACL.from_file(TEST_PATH).each do |e|
32
+ entry = e
33
+ end
34
+ assert_instance_of( ACL::Entry, entry ) # take individual ACL entry
35
+ assert_respond_to( entry, :qualifier ) # test existence of it's methods
36
+ assert_respond_to( entry, :qualifier= )
37
+ assert_respond_to( entry, :tag_type )
38
+ assert_respond_to( entry, :tag_type= )
39
+ assert_respond_to( entry, :permset )
40
+ assert_respond_to( entry, :permset= )
41
+
42
+ entry = a.create_entry # test creation of new ACL entry
43
+ entry.tag_type = ACL::ACL_USER
44
+ entry.qualifier = 1
45
+ entry.permset = 7
46
+
47
+ assert_equal( entry.tag_type, ACL::ACL_USER ) # test the getter/setter methods
48
+ assert_equal( entry.qualifier, 1 )
49
+ assert_equal( entry.permset, 7 )
50
+
51
+ # musime nastavit i masku!
52
+ entry2 = a.create_entry
53
+ entry2.tag_type = ACL::ACL_MASK
54
+ entry2.permset = 7
55
+
56
+ assert_equal( true, a.valid? ) # test call of the validity check function
57
+ end
58
+
59
+ def test_set
60
+ acl = ACL.from_file(TEST_PATH)
61
+ fname = File.join(TEST_PATH,'test')
62
+ FileUtils.mkpath(fname)
63
+
64
+ entry = acl.create_entry
65
+ entry.tag_type = ACL::ACL_USER
66
+ entry.qualifier = 1
67
+ entry.permset = 7
68
+
69
+ # musime nastavit i masku!
70
+ entry2 = acl.create_entry
71
+ entry2.tag_type = ACL::ACL_MASK
72
+ entry2.permset = 7
73
+
74
+ acl.set_file(fname) # test setting ACL on a file
75
+ # TODO: test default acl
76
+
77
+ acl2 = ACL.from_file(fname) # test, that the ACL was correctly set
78
+ assert_equal( acl.to_text, acl2.to_text )
79
+ end
80
+
81
+ # ruby -racl -e 'a = ACL.from_file(TEST_PATH); puts a.to_text; a.each { |e| p e; p e.qualifier; p e.tag_type; p e.permset }'
82
+
83
+ end
84
+
85
+ FileUtils.mkpath(ACLTest::TEST_PATH)
86
+
@@ -0,0 +1,419 @@
1
+ #include <ruby.h>
2
+
3
+ #include <sys/types.h>
4
+ #include <sys/acl.h>
5
+
6
+ VALUE cACL, cEntry;
7
+
8
+ void ruby_acl_free(acl_t acl) {
9
+ acl_free( acl );
10
+ }
11
+
12
+ #define Data_Get_Struct_ex(obj,type,sval) do {\
13
+ Check_Type(obj, T_DATA); \
14
+ sval = (type)DATA_PTR(obj);\
15
+ } while (0)
16
+
17
+ /*
18
+ * dump ACL as text
19
+ *
20
+ * call-seq:
21
+ * acl.to_text -> string
22
+ *
23
+ */
24
+ VALUE ruby_acl_to_text( VALUE self ) {
25
+ acl_t acl;
26
+ char *text;
27
+ VALUE ret;
28
+
29
+ Data_Get_Struct_ex( self, acl_t, acl );
30
+ if ( NULL == (text = acl_to_text( acl, NULL ) ) ) {
31
+ rb_sys_fail("acl_to_text returned error");
32
+ }
33
+ ret = rb_str_new2( text );
34
+ acl_free( text );
35
+
36
+ return ret;
37
+ }
38
+
39
+ /*
40
+ * iterate over ACL entries
41
+ *
42
+ * call-seq:
43
+ * acl.each { |entry| }
44
+ *
45
+ */
46
+ VALUE ruby_acl_each(VALUE self) {
47
+ int have;
48
+ acl_t acl;
49
+ acl_entry_t acl_entry;
50
+
51
+ Data_Get_Struct_ex( self, acl_t, acl );
52
+ have = acl_get_entry( acl, ACL_FIRST_ENTRY, &acl_entry );
53
+ while (have == 1) {
54
+ rb_yield( Data_Wrap_Struct( cEntry, 0, 0, acl_entry ) );
55
+ have = acl_get_entry( acl, ACL_NEXT_ENTRY, &acl_entry );
56
+ }
57
+ if (have != 0) rb_sys_fail("acl_get_entry returned error");
58
+
59
+ return self;
60
+ }
61
+
62
+ /*
63
+ * create new ACL object either by allocating new or duplicating given
64
+ * optional FIXNUM argument is passed to acl_init (number of entries to allocate)
65
+ *
66
+ * call-seq:
67
+ * ACL::new -> acl
68
+ * ACL::new( 10 ) -> acl
69
+ * ACL::new( acl ) -> acl
70
+ *
71
+ */
72
+ VALUE ruby_acl_new(int argc, VALUE *argv, VALUE class) {
73
+ acl_t acl;
74
+
75
+ switch (argc) {
76
+ case 0:
77
+ acl = acl_init(10);
78
+ break;
79
+ case 1: /* either copy constructor or given number of entries */
80
+ if (FIXNUM_P(argv[0])) {
81
+ if (NULL == (acl = acl_init( FIX2INT(argv[0]) ))) {
82
+ rb_sys_fail("acl_init returned error");
83
+ }
84
+ } else {
85
+ Data_Get_Struct_ex( argv[0], acl_t, acl );
86
+ if (NULL == (acl = acl_dup( acl ))) {
87
+ rb_sys_fail("acl_dup returned error");
88
+ }
89
+ }
90
+ break;
91
+ default:
92
+ rb_raise(rb_eArgError, "wrong number of arguments (expect 0 or 1)");
93
+ }
94
+ return Data_Wrap_Struct( class, 0, ruby_acl_free, acl );
95
+ }
96
+
97
+ /*
98
+ * create new ACL object from text representation of ACL
99
+ *
100
+ * call-seq:
101
+ * acl = ACL::from_text( string )
102
+ *
103
+ */
104
+ VALUE ruby_acl_from_text(VALUE class, VALUE text) {
105
+ acl_t acl;
106
+ if (NULL == (acl = acl_from_text( StringValuePtr(text) ))) {
107
+ rb_sys_fail("acl_from_text returned error");
108
+ }
109
+ return Data_Wrap_Struct( class, 0, ruby_acl_free, acl );
110
+ }
111
+
112
+ /*
113
+ * create new ACL object from filename or file descriptor (access ACL)
114
+ */
115
+ VALUE ruby_acl_from_file_fd(VALUE class, VALUE file) {
116
+ acl_t acl;
117
+ if (FIXNUM_P(file)) {
118
+ acl = acl_get_fd( FIX2INT(file) );
119
+ if ((acl_t)NULL==acl) rb_sys_fail("acl_get_fd failed");
120
+ } else {
121
+ acl = acl_get_file( StringValuePtr(file), ACL_TYPE_ACCESS );
122
+ if ((acl_t)NULL==acl) rb_sys_fail("acl_get_file failed");
123
+ }
124
+ return Data_Wrap_Struct( class, 0, ruby_acl_free, acl );
125
+ }
126
+
127
+ /*
128
+ * create new ACL object from directory name (default ACL)
129
+ */
130
+ VALUE ruby_acl_from_file_default(VALUE class, VALUE dir) {
131
+ acl_t acl;
132
+ acl = acl_get_file( StringValuePtr(dir), ACL_TYPE_DEFAULT );
133
+ if ((acl_t)NULL==acl) rb_sys_fail("acl_get_file failed");
134
+ return Data_Wrap_Struct( class, 0, ruby_acl_free, acl );
135
+ }
136
+
137
+ /*
138
+ * set ACL on file or fd
139
+ */
140
+ VALUE ruby_acl_set_file( VALUE self, VALUE file ) {
141
+ acl_t acl;
142
+
143
+ Data_Get_Struct_ex( self, acl_t, acl );
144
+
145
+ if (FIXNUM_P(file)) {
146
+ if (0 != acl_set_fd(FIX2INT(file), acl) ) {
147
+ rb_sys_fail("acl_set_fd failed");
148
+ }
149
+ } else {
150
+ //if (0 != acl_set_file( StringValueCStr(file), ACL_TYPE_ACCESS, acl ) ) {
151
+ if (0 != acl_set_file( StringValuePtr(file), ACL_TYPE_ACCESS, acl ) ) {
152
+ rb_sys_fail("acl_set_file (ACCESS ACL) failed");
153
+ }
154
+ }
155
+ return self;
156
+ }
157
+
158
+ /*
159
+ * set default ACL on directory
160
+ */
161
+ VALUE ruby_acl_set_default( VALUE self, VALUE dir ) {
162
+ acl_t acl;
163
+
164
+ Data_Get_Struct_ex( self, acl_t, acl );
165
+ if (0 != acl_set_file( StringValuePtr(dir), ACL_TYPE_DEFAULT, acl ) ) {
166
+ rb_sys_fail("acl_set_file (DEFAULT ACL) failed");
167
+ }
168
+ return self;
169
+ }
170
+
171
+ /*
172
+ * check if ACL is valid
173
+ *
174
+ * call-seq:
175
+ * acl.valid?
176
+ *
177
+ */
178
+ VALUE ruby_acl_valid( VALUE self ) {
179
+ acl_t acl;
180
+
181
+ Data_Get_Struct_ex( self, acl_t, acl );
182
+ if (0 == acl_valid( acl )) {
183
+ return Qtrue;
184
+ } else {
185
+ return Qfalse;
186
+ }
187
+ }
188
+
189
+ /*
190
+ * get ACL::Entry qualifier
191
+ */
192
+ VALUE ruby_acl_entry_get_qualifier( VALUE self ) {
193
+ acl_entry_t acl_entry;
194
+ int *ret;
195
+ VALUE val;
196
+
197
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
198
+ ret = acl_get_qualifier(acl_entry);
199
+ if ( NULL == ret ) return Qnil;
200
+ val = INT2FIX( *ret );
201
+ acl_free( ret );
202
+ return val;
203
+ }
204
+
205
+ /*
206
+ * set ACL::Entry qualifier
207
+ *
208
+ * call-seq:
209
+ * entry.qualifier = uid
210
+ * entry.qualifier = gid
211
+ *
212
+ */
213
+ VALUE ruby_acl_entry_set_qualifier( VALUE self, VALUE val ) {
214
+ int data;
215
+ acl_entry_t acl_entry;
216
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
217
+ data = FIX2INT(val);
218
+ if (0 != acl_set_qualifier(acl_entry, &data)) {
219
+ rb_sys_fail("acl_set_qualifier failed");
220
+ }
221
+ return self;
222
+ }
223
+
224
+ /*
225
+ * get ACL::Entry tag type
226
+ */
227
+ VALUE ruby_acl_entry_get_tag_type( VALUE self ) {
228
+ acl_entry_t acl_entry;
229
+ acl_tag_t acl_tag;
230
+
231
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
232
+ if (0 != acl_get_tag_type(acl_entry, &acl_tag)) {
233
+ rb_sys_fail("acl_set_qualifier failed");
234
+ }
235
+ return INT2FIX( acl_tag );
236
+ }
237
+
238
+ /*
239
+ * set ACL::Entry tag type
240
+ */
241
+ VALUE ruby_acl_entry_set_tag_type( VALUE self, VALUE val ) {
242
+ acl_entry_t acl_entry;
243
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
244
+ if (0 != acl_set_tag_type(acl_entry, FIX2INT(val))) {
245
+ rb_sys_fail("acl_set_tag_type failed");
246
+ }
247
+ return self;
248
+ }
249
+
250
+ /*
251
+ * get ACL::Entry permisions
252
+ */
253
+ VALUE ruby_acl_entry_get_permset( VALUE self ) {
254
+ acl_entry_t acl_entry;
255
+ acl_permset_t acl_permset;
256
+
257
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
258
+ if (0 != acl_get_permset(acl_entry, &acl_permset)) {
259
+ rb_sys_fail("acl_get_permset failed");
260
+ }
261
+ return INT2FIX(*(int*)acl_permset);
262
+ }
263
+
264
+ /*
265
+ * set ACL::Entry permisions
266
+ */
267
+ VALUE ruby_acl_entry_set_permset( VALUE self, VALUE val ) {
268
+ acl_entry_t acl_entry;
269
+ acl_permset_t acl_permset;
270
+ int perms;
271
+
272
+ Data_Get_Struct_ex( self, acl_entry_t, acl_entry );
273
+
274
+ if (0 != acl_get_permset(acl_entry, &acl_permset))
275
+ rb_sys_fail("acl_get_permset failed");
276
+ if (0 != acl_clear_perms(acl_permset))
277
+ rb_sys_fail("acl_clear_perms failed");
278
+
279
+ perms = FIX2INT(val);
280
+ //#define set_perm(perm) if (0!=acl_add_perm(acl_permset,perm)) rb_sys_fail("acl_add_perm failed")
281
+ //if (perms & 0x01) set_perm(ACL_EXECUTE);
282
+ //if (perms & 0x02) set_perm(ACL_WRITE);
283
+ //if (perms & 0x04) set_perm(ACL_READ);
284
+ if (0!=acl_add_perm(acl_permset,perms))
285
+ rb_sys_fail("acl_add_perm failed");
286
+
287
+ if (0 != acl_set_permset(acl_entry, acl_permset )) {
288
+ rb_sys_fail("acl_set_permset failed");
289
+ }
290
+ return self;
291
+ }
292
+
293
+ /*
294
+ * copy ACL::Entry into another
295
+ * entries can be in different ACLs
296
+ *
297
+ * call-seq:
298
+ * dest_entry = source_entry
299
+ *
300
+ */
301
+ VALUE ruby_acl_copy_entry( VALUE self, VALUE source ) {
302
+ acl_entry_t acl_dest, acl_source;
303
+
304
+ Data_Get_Struct_ex( self, acl_entry_t, acl_dest );
305
+ Data_Get_Struct_ex( source, acl_entry_t, acl_source );
306
+
307
+ if (0 != acl_copy_entry(acl_dest, acl_source)) {
308
+ rb_sys_fail("acl_copy_entry failed");
309
+ }
310
+ return self;
311
+ }
312
+
313
+ /*
314
+ * Create new entry in acl
315
+ *
316
+ * call-seq:
317
+ * entry = acl.create_entry
318
+ */
319
+ VALUE ruby_acl_create_entry( VALUE self ) {
320
+ acl_t acl;
321
+ acl_entry_t acl_entry;
322
+
323
+ Data_Get_Struct_ex( self, acl_t, acl );
324
+
325
+ if (0 != acl_create_entry( &acl, &acl_entry ) ) {
326
+ rb_sys_fail("acl_create_entry failed");
327
+ }
328
+ /* store the acl back into self */
329
+ DATA_PTR(self) = (void*)acl;
330
+ return Data_Wrap_Struct( cEntry, 0, 0, acl_entry );
331
+ }
332
+
333
+ /*
334
+ * Detele entry in ACL
335
+ *
336
+ * call-seq:
337
+ * acl.delete_entry( entry )
338
+ */
339
+ VALUE ruby_acl_delete_entry( VALUE self, VALUE entry ) {
340
+ acl_t acl;
341
+ acl_entry_t acl_entry;
342
+ Data_Get_Struct_ex( self, acl_t, acl );
343
+ Data_Get_Struct_ex( entry, acl_entry_t, acl_entry );
344
+
345
+ if (0 != acl_delete_entry( acl, acl_entry ) ) {
346
+ rb_sys_fail("acl_create_entry failed");
347
+ }
348
+ return self;
349
+ }
350
+
351
+ /*
352
+ * Document-class: ACL
353
+ * ACL -- interface to POSIX ACLs
354
+ *
355
+ * ACL represents access controll list associated with a file or directory.
356
+ *
357
+ * ACL instances are returned by methods ACL::from_text(text), ACL::from_file(file)
358
+ * or ACL::default(dir).
359
+ * Changes to ACL instances are not reflected back. You have to call ACL#set_file(file) or
360
+ * ACL#set_default(dir) to applly changes back to the filesystem.
361
+ */
362
+
363
+ /*
364
+ * Document-class: ACL::Entry
365
+ * ACL::Entry represents single entry of ACL.
366
+ *
367
+ * Entries have the formL tag_type, permset, qualifier.
368
+ */
369
+ void Init_acl(void) {
370
+ cACL = rb_define_class( "ACL", rb_cObject );
371
+ cEntry = rb_define_class_under( cACL, "Entry", rb_cObject );
372
+
373
+ /* Constructors */
374
+ rb_define_singleton_method( cACL, "new", ruby_acl_new, -1 );
375
+ rb_define_singleton_method( cACL, "from_text", ruby_acl_from_text, 1 );
376
+ rb_define_singleton_method( cACL, "from_file", ruby_acl_from_file_fd, 1 );
377
+ rb_define_singleton_method( cACL, "default", ruby_acl_from_file_default, 1 );
378
+
379
+ /* Setting ACL */
380
+ rb_define_method( cACL, "set_file", ruby_acl_set_file, 1 );
381
+ rb_define_method( cACL, "set_default", ruby_acl_set_default, 1 );
382
+
383
+ /* Other methods */
384
+ rb_define_method( cACL, "to_text", ruby_acl_to_text, 0 );
385
+ rb_define_method( cACL, "each", ruby_acl_each, 0 );
386
+ rb_define_method( cACL, "valid?", ruby_acl_valid, 0 );
387
+
388
+ rb_define_method( cACL, "create_entry", ruby_acl_create_entry, 0 );
389
+ rb_define_method( cACL, "delete_entry", ruby_acl_delete_entry, 1 );
390
+
391
+ rb_include_module( cACL, rb_mEnumerable );
392
+
393
+ /* Manipulating with ACL entry */
394
+ rb_define_method( cEntry, "qualifier", ruby_acl_entry_get_qualifier, 0 );
395
+ rb_define_method( cEntry, "qualifier=", ruby_acl_entry_set_qualifier, 1 );
396
+ rb_define_method( cEntry, "tag_type", ruby_acl_entry_get_tag_type, 0 );
397
+ rb_define_method( cEntry, "tag_type=", ruby_acl_entry_set_tag_type, 1 );
398
+ rb_define_method( cEntry, "permset", ruby_acl_entry_get_permset, 0 );
399
+ rb_define_method( cEntry, "permset=", ruby_acl_entry_set_permset, 1 );
400
+ rb_define_method( cEntry, "=", ruby_acl_copy_entry, 1 );
401
+ /*
402
+ * not implementing:
403
+ * acl_add_perm(3), acl_clear_perms(3), acl_delete_perm(3), acl_get_perm(3),
404
+ */
405
+
406
+ /* Tag type constants */
407
+ rb_define_const( cACL, "ACL_UNDEFINED_TAG", INT2FIX(ACL_UNDEFINED_TAG) );
408
+ rb_define_const( cACL, "ACL_USER_OBJ" , INT2FIX(ACL_USER_OBJ) );
409
+ rb_define_const( cACL, "ACL_USER" , INT2FIX(ACL_USER) );
410
+ rb_define_const( cACL, "ACL_GROUP_OBJ" , INT2FIX(ACL_GROUP_OBJ) );
411
+ rb_define_const( cACL, "ACL_GROUP" , INT2FIX(ACL_GROUP) );
412
+ rb_define_const( cACL, "ACL_MASK" , INT2FIX(ACL_MASK) );
413
+ rb_define_const( cACL, "ACL_OTHER" , INT2FIX(ACL_OTHER) );
414
+ /* Permition constants */
415
+ rb_define_const( cACL, "ACL_EXECUTE" , INT2FIX(ACL_EXECUTE) );
416
+ rb_define_const( cACL, "ACL_WRITE" , INT2FIX(ACL_WRITE) );
417
+ rb_define_const( cACL, "ACL_READ" , INT2FIX(ACL_READ) );
418
+ }
419
+
@@ -0,0 +1,20 @@
1
+ require 'mkmf'
2
+
3
+ have_library('acl','acl_get_file')
4
+ create_makefile("acl")
5
+
6
+ rdoc = find_executable0( 'rdoc' ) || find_executable0( 'rdoc1.8' )
7
+
8
+ File.open('Makefile', "a") do |f|
9
+ f << <<EOS
10
+ doc: acl.c acl.rb
11
+ #{rdoc} $^
12
+
13
+ dist: acl.c extconf.rb README copyright t/test.rb
14
+ mkdir -p acl-ruby
15
+ cp --parents $^ acl-ruby/
16
+ tar cvjf acl.tar.bz2 acl-ruby/
17
+ rm -rf acl-ruby
18
+
19
+ EOS
20
+ end
@@ -0,0 +1,19 @@
1
+ require 'acl.so'
2
+
3
+ class File
4
+ def acl
5
+ ACL.from_file(fileno)
6
+ end
7
+
8
+ def default_acl
9
+ ACL.default(fileno)
10
+ end
11
+
12
+ def acl=(acl)
13
+ acl.set_file(fileno)
14
+ end
15
+
16
+ def default_acl=(acl)
17
+ acl.set_default(fileno)
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module ACL
2
+ VERSION = 0.1
3
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acl
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Martin Povolny
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-12 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+ description: Bindings for POSIX ACL
16
+ email:
17
+ - martin.povolny@gmail.com
18
+ executables: []
19
+ extensions:
20
+ - ext/acl/extconf.rb
21
+ extra_rdoc_files:
22
+ - ext/acl/acl.c
23
+ files:
24
+ - acl/t/test.rb
25
+ - ext/acl/acl.c
26
+ - ext/acl/extconf.rb
27
+ - lib/acl/acl.rb
28
+ - lib/acl/version.rb
29
+ has_rdoc: true
30
+ homepage: https://github.com/martinpovolny/libacl-ruby
31
+ licenses: []
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 1.6.2
51
+ signing_key:
52
+ specification_version: 3
53
+ summary: Posix ACL bindings
54
+ test_files: []