acl 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []