ruby-magic 0.3.2 → 0.5.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/CONTRIBUTORS.md +2 -1
- data/dependencies.yml +22 -0
- data/ext/magic/common.h +39 -21
- data/ext/magic/extconf.rb +79 -10
- data/ext/magic/functions.c +32 -14
- data/ext/magic/functions.h +18 -12
- data/ext/magic/ruby-magic.c +548 -330
- data/ext/magic/ruby-magic.h +214 -60
- data/lib/magic/version.rb +1 -1
- data/lib/magic.rb +19 -1
- metadata +10 -10
data/ext/magic/ruby-magic.c
CHANGED
@@ -11,51 +11,68 @@ static int rb_mgc_warning;
|
|
11
11
|
static ID id_at_flags;
|
12
12
|
static ID id_at_paths;
|
13
13
|
|
14
|
-
static VALUE rb_cMagic
|
14
|
+
static VALUE rb_cMagic;
|
15
15
|
|
16
|
-
static VALUE rb_mgc_eError
|
17
|
-
static VALUE rb_mgc_eMagicError
|
18
|
-
static VALUE rb_mgc_eLibraryError
|
19
|
-
static VALUE
|
20
|
-
static VALUE
|
21
|
-
static VALUE
|
16
|
+
static VALUE rb_mgc_eError;
|
17
|
+
static VALUE rb_mgc_eMagicError;
|
18
|
+
static VALUE rb_mgc_eLibraryError;
|
19
|
+
static VALUE rb_mgc_eNotImplementedError;
|
20
|
+
static VALUE rb_mgc_eParameterError;
|
21
|
+
static VALUE rb_mgc_eFlagsError;
|
22
22
|
|
23
|
-
|
23
|
+
static const rb_data_type_t rb_mgc_type;
|
24
24
|
|
25
25
|
static VALUE magic_get_parameter_internal(void *data);
|
26
26
|
static VALUE magic_set_parameter_internal(void *data);
|
27
|
+
|
27
28
|
static VALUE magic_get_flags_internal(void *data);
|
28
29
|
static VALUE magic_set_flags_internal(void *data);
|
30
|
+
|
29
31
|
static VALUE magic_load_internal(void *data);
|
30
32
|
static VALUE magic_load_buffers_internal(void *data);
|
33
|
+
|
31
34
|
static VALUE magic_compile_internal(void *data);
|
32
35
|
static VALUE magic_check_internal(void *data);
|
36
|
+
|
33
37
|
static VALUE magic_file_internal(void *data);
|
34
38
|
static VALUE magic_buffer_internal(void *data);
|
35
39
|
static VALUE magic_descriptor_internal(void *data);
|
40
|
+
|
36
41
|
static VALUE magic_close_internal(void *data);
|
37
42
|
|
38
|
-
static void*
|
39
|
-
static void*
|
40
|
-
static void*
|
41
|
-
static void*
|
42
|
-
static void*
|
43
|
+
static void *nogvl_magic_load(void *data);
|
44
|
+
static void *nogvl_magic_compile(void *data);
|
45
|
+
static void *nogvl_magic_check(void *data);
|
46
|
+
static void *nogvl_magic_file(void *data);
|
47
|
+
static void *nogvl_magic_descriptor(void *data);
|
48
|
+
|
49
|
+
static void *magic_library_open(void);
|
50
|
+
static void magic_library_close(void *data);
|
43
51
|
|
44
52
|
static VALUE magic_allocate(VALUE klass);
|
45
53
|
static void magic_mark(void *data);
|
46
54
|
static void magic_free(void *data);
|
55
|
+
static size_t magic_size(const void *data);
|
56
|
+
#if defined(HAVE_RUBY_GC_COMPACT)
|
57
|
+
static void magic_compact(void *data);
|
58
|
+
#endif
|
59
|
+
|
47
60
|
static VALUE magic_exception_wrapper(VALUE value);
|
48
61
|
static VALUE magic_exception(void *data);
|
49
|
-
|
62
|
+
|
50
63
|
static VALUE magic_library_error(VALUE klass, void *data);
|
51
64
|
static VALUE magic_generic_error(VALUE klass, int magic_errno,
|
52
65
|
const char *magic_error);
|
66
|
+
|
53
67
|
static VALUE magic_lock(VALUE object, VALUE (*function)(ANYARGS),
|
54
68
|
void *data);
|
55
69
|
static VALUE magic_unlock(VALUE object);
|
70
|
+
|
56
71
|
static VALUE magic_return(void *data);
|
57
|
-
|
58
|
-
static int
|
72
|
+
|
73
|
+
static int magic_get_flags(VALUE object);
|
74
|
+
static void magic_set_flags(VALUE object, int flags);
|
75
|
+
|
59
76
|
static VALUE magic_set_paths(VALUE object, VALUE value);
|
60
77
|
|
61
78
|
/*
|
@@ -110,6 +127,7 @@ VALUE
|
|
110
127
|
rb_mgc_set_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object), VALUE value)
|
111
128
|
{
|
112
129
|
rb_mgc_do_not_auto_load = RVAL2CBOOL(value);
|
130
|
+
|
113
131
|
return value;
|
114
132
|
}
|
115
133
|
|
@@ -150,6 +168,7 @@ VALUE
|
|
150
168
|
rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
|
151
169
|
{
|
152
170
|
rb_mgc_do_not_stop_on_error = RVAL2CBOOL(value);
|
171
|
+
|
153
172
|
return value;
|
154
173
|
}
|
155
174
|
|
@@ -171,7 +190,7 @@ rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
|
|
171
190
|
VALUE
|
172
191
|
rb_mgc_initialize(VALUE object, VALUE arguments)
|
173
192
|
{
|
174
|
-
|
193
|
+
rb_mgc_object_t *mgc;
|
175
194
|
const char *klass = "Magic";
|
176
195
|
|
177
196
|
if (!NIL_P(object))
|
@@ -181,21 +200,22 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
|
|
181
200
|
MAGIC_WARNING(0, "%s::new() does not take block; use %s::open() instead",
|
182
201
|
klass, klass);
|
183
202
|
|
184
|
-
if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
|
203
|
+
if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
|
185
204
|
rb_mgc_do_not_stop_on_error = 1;
|
186
205
|
|
187
|
-
if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
|
206
|
+
if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
|
188
207
|
rb_mgc_do_not_auto_load = 1;
|
189
208
|
|
190
|
-
MAGIC_OBJECT(
|
191
|
-
|
209
|
+
MAGIC_OBJECT(object, mgc);
|
210
|
+
|
211
|
+
mgc->stop_on_errors = 1;
|
192
212
|
if (rb_mgc_do_not_stop_on_error)
|
193
|
-
|
213
|
+
mgc->stop_on_errors = 0;
|
194
214
|
|
195
|
-
|
196
|
-
|
215
|
+
mgc->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject,
|
216
|
+
rb_intern("Mutex")));
|
197
217
|
|
198
|
-
magic_set_flags(object,
|
218
|
+
magic_set_flags(object, MAGIC_NONE);
|
199
219
|
magic_set_paths(object, RARRAY_EMPTY);
|
200
220
|
|
201
221
|
if (rb_mgc_do_not_auto_load) {
|
@@ -207,6 +227,7 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
|
|
207
227
|
}
|
208
228
|
|
209
229
|
rb_mgc_load(object, arguments);
|
230
|
+
|
210
231
|
return object;
|
211
232
|
}
|
212
233
|
|
@@ -219,12 +240,12 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
|
|
219
240
|
VALUE
|
220
241
|
rb_mgc_get_do_not_stop_on_error(VALUE object)
|
221
242
|
{
|
222
|
-
|
243
|
+
rb_mgc_object_t *mgc;
|
223
244
|
|
224
245
|
MAGIC_CHECK_OPEN(object);
|
225
|
-
MAGIC_OBJECT(
|
246
|
+
MAGIC_OBJECT(object, mgc);
|
226
247
|
|
227
|
-
return CBOOL2RVAL(!
|
248
|
+
return CBOOL2RVAL(!mgc->stop_on_errors);
|
228
249
|
}
|
229
250
|
|
230
251
|
/*
|
@@ -236,12 +257,13 @@ rb_mgc_get_do_not_stop_on_error(VALUE object)
|
|
236
257
|
VALUE
|
237
258
|
rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value)
|
238
259
|
{
|
239
|
-
|
260
|
+
rb_mgc_object_t *mgc;
|
240
261
|
|
241
262
|
MAGIC_CHECK_OPEN(object);
|
242
|
-
MAGIC_OBJECT(
|
263
|
+
MAGIC_OBJECT(object, mgc);
|
264
|
+
|
265
|
+
mgc->stop_on_errors = !RVAL2CBOOL(value);
|
243
266
|
|
244
|
-
mo->stop_on_errors = !RVAL2CBOOL(value);
|
245
267
|
return value;
|
246
268
|
}
|
247
269
|
|
@@ -283,14 +305,15 @@ rb_mgc_open_p(VALUE object)
|
|
283
305
|
VALUE
|
284
306
|
rb_mgc_close(VALUE object)
|
285
307
|
{
|
286
|
-
|
308
|
+
rb_mgc_object_t *mgc;
|
287
309
|
|
288
310
|
if (MAGIC_CLOSED_P(object))
|
289
311
|
return Qnil;
|
290
312
|
|
291
|
-
MAGIC_OBJECT(
|
292
|
-
|
293
|
-
|
313
|
+
MAGIC_OBJECT(object, mgc);
|
314
|
+
|
315
|
+
if (mgc) {
|
316
|
+
MAGIC_SYNCHRONIZED(magic_close_internal, mgc);
|
294
317
|
if (DATA_P(object))
|
295
318
|
DATA_PTR(object) = NULL;
|
296
319
|
}
|
@@ -317,12 +340,13 @@ rb_mgc_close(VALUE object)
|
|
317
340
|
VALUE
|
318
341
|
rb_mgc_close_p(VALUE object)
|
319
342
|
{
|
320
|
-
|
343
|
+
rb_mgc_object_t *mgc;
|
321
344
|
magic_t cookie = NULL;
|
322
345
|
|
323
|
-
MAGIC_OBJECT(
|
324
|
-
|
325
|
-
|
346
|
+
MAGIC_OBJECT(object, mgc);
|
347
|
+
|
348
|
+
if (mgc)
|
349
|
+
cookie = mgc->cookie;
|
326
350
|
|
327
351
|
if (DATA_P(object) && cookie)
|
328
352
|
return Qfalse;
|
@@ -349,14 +373,17 @@ rb_mgc_get_paths(VALUE object)
|
|
349
373
|
MAGIC_CHECK_OPEN(object);
|
350
374
|
|
351
375
|
value = rb_ivar_get(object, id_at_paths);
|
352
|
-
if (!NIL_P(value) && !RARRAY_EMPTY_P(value)
|
376
|
+
if (!NIL_P(value) && !RARRAY_EMPTY_P(value))
|
353
377
|
return value;
|
354
378
|
|
355
|
-
|
356
|
-
|
357
|
-
|
379
|
+
value = rb_funcall(rb_cMagic, rb_intern("default_paths"), 0);
|
380
|
+
if (getenv("MAGIC") || NIL_P(value)) {
|
381
|
+
cstring = magic_getpath_wrapper();
|
382
|
+
value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":"));
|
383
|
+
RB_GC_GUARD(value);
|
384
|
+
}
|
358
385
|
|
359
|
-
return value;
|
386
|
+
return magic_set_paths(object, value);
|
360
387
|
}
|
361
388
|
|
362
389
|
/*
|
@@ -367,28 +394,34 @@ VALUE
|
|
367
394
|
rb_mgc_get_parameter(VALUE object, VALUE tag)
|
368
395
|
{
|
369
396
|
int local_errno;
|
370
|
-
|
371
|
-
|
397
|
+
rb_mgc_object_t *mgc;
|
398
|
+
rb_mgc_arguments_t mga;
|
372
399
|
|
373
400
|
MAGIC_CHECK_INTEGER_TYPE(tag);
|
401
|
+
|
374
402
|
MAGIC_CHECK_OPEN(object);
|
375
|
-
|
403
|
+
MAGIC_OBJECT(object, mgc);
|
376
404
|
|
377
|
-
|
405
|
+
mga = (rb_mgc_arguments_t) {
|
406
|
+
.magic_object = mgc,
|
407
|
+
.parameter = {
|
408
|
+
.tag = NUM2INT(tag),
|
409
|
+
},
|
410
|
+
};
|
378
411
|
|
379
|
-
MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &
|
412
|
+
MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &mga);
|
380
413
|
local_errno = errno;
|
381
414
|
|
382
|
-
if (
|
415
|
+
if (mga.status < 0) {
|
383
416
|
if (local_errno == EINVAL)
|
384
417
|
MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
|
385
418
|
local_errno,
|
386
419
|
E_PARAM_INVALID_TYPE);
|
387
420
|
|
388
|
-
MAGIC_LIBRARY_ERROR(
|
421
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
389
422
|
}
|
390
423
|
|
391
|
-
return SIZET2NUM(
|
424
|
+
return SIZET2NUM(mga.parameter.value);
|
392
425
|
}
|
393
426
|
|
394
427
|
/*
|
@@ -399,21 +432,27 @@ VALUE
|
|
399
432
|
rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
|
400
433
|
{
|
401
434
|
int local_errno;
|
402
|
-
|
403
|
-
|
435
|
+
rb_mgc_object_t *mgc;
|
436
|
+
rb_mgc_arguments_t mga;
|
404
437
|
|
405
438
|
MAGIC_CHECK_INTEGER_TYPE(tag);
|
406
439
|
MAGIC_CHECK_INTEGER_TYPE(value);
|
440
|
+
|
407
441
|
MAGIC_CHECK_OPEN(object);
|
408
|
-
|
442
|
+
MAGIC_OBJECT(object, mgc);
|
409
443
|
|
410
|
-
|
411
|
-
|
444
|
+
mga = (rb_mgc_arguments_t) {
|
445
|
+
.magic_object = mgc,
|
446
|
+
.parameter = {
|
447
|
+
.tag = NUM2INT(tag),
|
448
|
+
.value = NUM2SIZET(value),
|
449
|
+
},
|
450
|
+
};
|
412
451
|
|
413
|
-
MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &
|
452
|
+
MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &mga);
|
414
453
|
local_errno = errno;
|
415
454
|
|
416
|
-
if (
|
455
|
+
if (mga.status < 0) {
|
417
456
|
switch (local_errno) {
|
418
457
|
case EINVAL:
|
419
458
|
MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
|
@@ -424,7 +463,8 @@ rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
|
|
424
463
|
local_errno,
|
425
464
|
E_PARAM_INVALID_VALUE);
|
426
465
|
}
|
427
|
-
|
466
|
+
|
467
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
428
468
|
}
|
429
469
|
|
430
470
|
return Qnil;
|
@@ -447,19 +487,23 @@ VALUE
|
|
447
487
|
rb_mgc_get_flags(VALUE object)
|
448
488
|
{
|
449
489
|
int local_errno;
|
450
|
-
|
451
|
-
|
490
|
+
rb_mgc_object_t *mgc;
|
491
|
+
rb_mgc_arguments_t mga;
|
452
492
|
|
453
493
|
MAGIC_CHECK_OPEN(object);
|
454
|
-
|
494
|
+
MAGIC_OBJECT(object, mgc);
|
495
|
+
|
496
|
+
mga = (rb_mgc_arguments_t) {
|
497
|
+
.magic_object = mgc,
|
498
|
+
};
|
455
499
|
|
456
|
-
MAGIC_SYNCHRONIZED(magic_get_flags_internal, &
|
500
|
+
MAGIC_SYNCHRONIZED(magic_get_flags_internal, &mga);
|
457
501
|
local_errno = errno;
|
458
502
|
|
459
|
-
if (
|
503
|
+
if (mga.status < 0 && local_errno == ENOSYS)
|
460
504
|
return rb_ivar_get(object, id_at_flags);
|
461
505
|
|
462
|
-
return INT2NUM(
|
506
|
+
return INT2NUM(mga.flags);
|
463
507
|
}
|
464
508
|
|
465
509
|
/*
|
@@ -476,19 +520,43 @@ VALUE
|
|
476
520
|
rb_mgc_set_flags(VALUE object, VALUE value)
|
477
521
|
{
|
478
522
|
int local_errno;
|
479
|
-
|
480
|
-
|
523
|
+
rb_mgc_object_t *mgc;
|
524
|
+
rb_mgc_arguments_t mga;
|
525
|
+
const char *klass = "Magic";
|
526
|
+
const char *flag = NULL;
|
481
527
|
|
482
528
|
MAGIC_CHECK_INTEGER_TYPE(value);
|
529
|
+
|
483
530
|
MAGIC_CHECK_OPEN(object);
|
484
|
-
|
531
|
+
MAGIC_OBJECT(object, mgc);
|
532
|
+
|
533
|
+
mga = (rb_mgc_arguments_t) {
|
534
|
+
.magic_object = mgc,
|
535
|
+
.flags = NUM2INT(value),
|
536
|
+
};
|
537
|
+
|
538
|
+
if (mga.flags < 0)
|
539
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError, EINVAL,
|
540
|
+
E_FLAG_INVALID_TYPE);
|
541
|
+
|
542
|
+
if (mga.flags & MAGIC_DEBUG)
|
543
|
+
flag = "DEBUG";
|
544
|
+
else if (mga.flags & MAGIC_CHECK)
|
545
|
+
flag = "CHECK";
|
546
|
+
|
547
|
+
if (flag) {
|
548
|
+
if (!NIL_P(object))
|
549
|
+
klass = rb_obj_classname(object);
|
485
550
|
|
486
|
-
|
551
|
+
MAGIC_WARNING(0, "%s::%s flag is set; verbose information will "
|
552
|
+
"now be printed to the standard error output",
|
553
|
+
klass, flag);
|
554
|
+
}
|
487
555
|
|
488
|
-
MAGIC_SYNCHRONIZED(magic_set_flags_internal, &
|
556
|
+
MAGIC_SYNCHRONIZED(magic_set_flags_internal, &mga);
|
489
557
|
local_errno = errno;
|
490
558
|
|
491
|
-
if (
|
559
|
+
if (mga.status < 0) {
|
492
560
|
switch (local_errno) {
|
493
561
|
case EINVAL:
|
494
562
|
MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError,
|
@@ -499,10 +567,11 @@ rb_mgc_set_flags(VALUE object, VALUE value)
|
|
499
567
|
local_errno,
|
500
568
|
E_FLAG_NOT_IMPLEMENTED);
|
501
569
|
}
|
502
|
-
|
570
|
+
|
571
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
503
572
|
}
|
504
573
|
|
505
|
-
return rb_ivar_set(object, id_at_flags, INT2NUM(
|
574
|
+
return rb_ivar_set(object, id_at_flags, INT2NUM(mga.flags));
|
506
575
|
}
|
507
576
|
|
508
577
|
/*
|
@@ -518,8 +587,8 @@ rb_mgc_set_flags(VALUE object, VALUE value)
|
|
518
587
|
VALUE
|
519
588
|
rb_mgc_load(VALUE object, VALUE arguments)
|
520
589
|
{
|
521
|
-
|
522
|
-
|
590
|
+
rb_mgc_object_t *mgc;
|
591
|
+
rb_mgc_arguments_t mga;
|
523
592
|
const char *klass = "Magic";
|
524
593
|
VALUE value = Qundef;
|
525
594
|
|
@@ -527,40 +596,48 @@ rb_mgc_load(VALUE object, VALUE arguments)
|
|
527
596
|
arguments = magic_flatten(arguments);
|
528
597
|
|
529
598
|
MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
|
599
|
+
|
530
600
|
MAGIC_CHECK_OPEN(object);
|
531
|
-
|
601
|
+
MAGIC_OBJECT(object, mgc);
|
532
602
|
|
533
603
|
if (rb_mgc_do_not_auto_load) {
|
534
604
|
if (!NIL_P(object))
|
535
605
|
klass = rb_obj_classname(object);
|
536
606
|
|
537
607
|
MAGIC_WARNING(2, "%s::do_not_auto_load is set; using %s#load "
|
538
|
-
|
539
|
-
|
608
|
+
"will load Magic database from a file",
|
609
|
+
klass, klass);
|
540
610
|
}
|
541
611
|
|
542
|
-
|
612
|
+
if (RARRAY_EMPTY_P(arguments))
|
613
|
+
arguments = rb_mgc_get_paths(object);
|
543
614
|
|
544
|
-
|
545
|
-
|
546
|
-
ma.type.file.path = RVAL2CSTR(value);
|
547
|
-
}
|
548
|
-
else
|
549
|
-
ma.type.file.path = magic_getpath_wrapper();
|
615
|
+
value = magic_join(arguments, CSTR2RVAL(":"));
|
616
|
+
RB_GC_GUARD(value);
|
550
617
|
|
551
618
|
magic_set_paths(object, RARRAY_EMPTY);
|
552
619
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
620
|
+
mga = (rb_mgc_arguments_t) {
|
621
|
+
.magic_object = mgc,
|
622
|
+
.file = {
|
623
|
+
.path = RVAL2CSTR(value),
|
624
|
+
},
|
625
|
+
.flags = magic_get_flags(object),
|
626
|
+
};
|
627
|
+
|
628
|
+
MAGIC_SYNCHRONIZED(magic_load_internal, &mga);
|
629
|
+
if (mga.status < 0) {
|
630
|
+
mgc->database_loaded = 0;
|
631
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
557
632
|
}
|
558
|
-
mo->database_loaded = 1;
|
559
633
|
|
560
|
-
|
561
|
-
|
634
|
+
mgc->database_loaded = 1;
|
635
|
+
|
636
|
+
value = magic_split(CSTR2RVAL(mga.file.path), CSTR2RVAL(":"));
|
562
637
|
RB_GC_GUARD(value);
|
563
638
|
|
639
|
+
magic_set_paths(object, value);
|
640
|
+
|
564
641
|
return Qnil;
|
565
642
|
}
|
566
643
|
|
@@ -576,8 +653,8 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
|
|
576
653
|
{
|
577
654
|
size_t count;
|
578
655
|
int local_errno;
|
579
|
-
|
580
|
-
|
656
|
+
rb_mgc_object_t *mgc;
|
657
|
+
rb_mgc_arguments_t mga;
|
581
658
|
void **pointers = NULL;
|
582
659
|
size_t *sizes = NULL;
|
583
660
|
VALUE value = Qundef;
|
@@ -592,8 +669,9 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
|
|
592
669
|
|
593
670
|
MAGIC_CHECK_ARRAY_EMPTY(arguments);
|
594
671
|
MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
|
672
|
+
|
595
673
|
MAGIC_CHECK_OPEN(object);
|
596
|
-
|
674
|
+
MAGIC_OBJECT(object, mgc);
|
597
675
|
|
598
676
|
pointers = ALLOC_N(void *, count);
|
599
677
|
if (!pointers) {
|
@@ -614,35 +692,41 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
|
|
614
692
|
sizes[i] = (size_t)RSTRING_LEN(value);
|
615
693
|
}
|
616
694
|
|
617
|
-
ma.flags = magic_flags(object);
|
618
|
-
ma.type.buffers.count = count;
|
619
|
-
ma.type.buffers.pointers = pointers;
|
620
|
-
ma.type.buffers.sizes = sizes;
|
621
|
-
|
622
695
|
magic_set_paths(object, RARRAY_EMPTY);
|
623
696
|
|
624
|
-
|
625
|
-
|
697
|
+
mga = (rb_mgc_arguments_t) {
|
698
|
+
.magic_object = mgc,
|
699
|
+
.buffers = {
|
700
|
+
.count = count,
|
701
|
+
.pointers = pointers,
|
702
|
+
.sizes = sizes,
|
703
|
+
},
|
704
|
+
.flags = magic_get_flags(object),
|
705
|
+
};
|
706
|
+
|
707
|
+
MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &mga);
|
708
|
+
if (mga.status < 0) {
|
626
709
|
local_errno = errno;
|
627
710
|
ruby_xfree(pointers);
|
628
711
|
ruby_xfree(sizes);
|
629
712
|
goto error;
|
630
713
|
}
|
631
|
-
|
714
|
+
|
715
|
+
mgc->database_loaded = 1;
|
632
716
|
|
633
717
|
ruby_xfree(pointers);
|
634
718
|
ruby_xfree(sizes);
|
635
719
|
|
636
720
|
return Qnil;
|
637
721
|
error:
|
638
|
-
|
722
|
+
mgc->database_loaded = 0;
|
639
723
|
|
640
724
|
if (local_errno == ENOMEM)
|
641
725
|
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
642
726
|
local_errno,
|
643
727
|
E_NOT_ENOUGH_MEMORY);
|
644
728
|
|
645
|
-
MAGIC_LIBRARY_ERROR(
|
729
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
646
730
|
}
|
647
731
|
|
648
732
|
/*
|
@@ -669,12 +753,12 @@ error:
|
|
669
753
|
VALUE
|
670
754
|
rb_mgc_load_p(VALUE object)
|
671
755
|
{
|
672
|
-
|
756
|
+
rb_mgc_object_t *mgc;
|
673
757
|
|
674
758
|
MAGIC_CHECK_OPEN(object);
|
675
|
-
MAGIC_OBJECT(
|
759
|
+
MAGIC_OBJECT(object, mgc);
|
676
760
|
|
677
|
-
return CBOOL2RVAL(
|
761
|
+
return CBOOL2RVAL(mgc->database_loaded);
|
678
762
|
}
|
679
763
|
|
680
764
|
/*
|
@@ -687,19 +771,25 @@ rb_mgc_load_p(VALUE object)
|
|
687
771
|
VALUE
|
688
772
|
rb_mgc_compile(VALUE object, VALUE value)
|
689
773
|
{
|
690
|
-
|
691
|
-
|
774
|
+
rb_mgc_object_t *mgc;
|
775
|
+
rb_mgc_arguments_t mga;
|
692
776
|
|
693
777
|
MAGIC_CHECK_STRING_TYPE(value);
|
778
|
+
|
694
779
|
MAGIC_CHECK_OPEN(object);
|
695
|
-
|
780
|
+
MAGIC_OBJECT(object, mgc);
|
696
781
|
|
697
|
-
|
698
|
-
|
782
|
+
mga = (rb_mgc_arguments_t) {
|
783
|
+
.magic_object = mgc,
|
784
|
+
.file = {
|
785
|
+
.path = RVAL2CSTR(value),
|
786
|
+
},
|
787
|
+
.flags = magic_get_flags(object),
|
788
|
+
};
|
699
789
|
|
700
|
-
MAGIC_SYNCHRONIZED(magic_compile_internal, &
|
701
|
-
if (
|
702
|
-
MAGIC_LIBRARY_ERROR(
|
790
|
+
MAGIC_SYNCHRONIZED(magic_compile_internal, &mga);
|
791
|
+
if (mga.status < 0)
|
792
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
703
793
|
|
704
794
|
return Qnil;
|
705
795
|
}
|
@@ -714,18 +804,25 @@ rb_mgc_compile(VALUE object, VALUE value)
|
|
714
804
|
VALUE
|
715
805
|
rb_mgc_check(VALUE object, VALUE value)
|
716
806
|
{
|
717
|
-
|
718
|
-
|
807
|
+
rb_mgc_object_t *mgc;
|
808
|
+
rb_mgc_arguments_t mga;
|
719
809
|
|
720
810
|
MAGIC_CHECK_STRING_TYPE(value);
|
811
|
+
|
721
812
|
MAGIC_CHECK_OPEN(object);
|
722
|
-
|
813
|
+
MAGIC_OBJECT(object, mgc);
|
814
|
+
|
815
|
+
mga = (rb_mgc_arguments_t) {
|
816
|
+
.magic_object = mgc,
|
817
|
+
.file = {
|
818
|
+
.path = RVAL2CSTR(value),
|
819
|
+
},
|
820
|
+
.flags = magic_get_flags(object),
|
821
|
+
};
|
723
822
|
|
724
|
-
|
725
|
-
ma.type.file.path = RVAL2CSTR(value);
|
823
|
+
MAGIC_SYNCHRONIZED(magic_check_internal, &mga);
|
726
824
|
|
727
|
-
|
728
|
-
return ma.status < 0 ? Qfalse : Qtrue;
|
825
|
+
return mga.status < 0 ? Qfalse : Qtrue;
|
729
826
|
}
|
730
827
|
|
731
828
|
/*
|
@@ -738,8 +835,8 @@ rb_mgc_check(VALUE object, VALUE value)
|
|
738
835
|
VALUE
|
739
836
|
rb_mgc_file(VALUE object, VALUE value)
|
740
837
|
{
|
741
|
-
|
742
|
-
|
838
|
+
rb_mgc_object_t *mgc;
|
839
|
+
rb_mgc_arguments_t mga;
|
743
840
|
const char *empty = "(null)";
|
744
841
|
|
745
842
|
UNUSED(empty);
|
@@ -749,7 +846,7 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
749
846
|
|
750
847
|
MAGIC_CHECK_OPEN(object);
|
751
848
|
MAGIC_CHECK_LOADED(object);
|
752
|
-
|
849
|
+
MAGIC_OBJECT(object, mgc);
|
753
850
|
|
754
851
|
if (rb_respond_to(value, rb_intern("to_io")))
|
755
852
|
return rb_mgc_descriptor(object, value);
|
@@ -758,12 +855,16 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
758
855
|
if (NIL_P(value))
|
759
856
|
goto error;
|
760
857
|
|
761
|
-
|
762
|
-
|
763
|
-
|
858
|
+
mga = (rb_mgc_arguments_t) {
|
859
|
+
.magic_object = mgc,
|
860
|
+
.file = {
|
861
|
+
.path = RVAL2CSTR(value),
|
862
|
+
},
|
863
|
+
.flags = magic_get_flags(object),
|
864
|
+
};
|
764
865
|
|
765
|
-
MAGIC_SYNCHRONIZED(magic_file_internal, &
|
766
|
-
if (
|
866
|
+
MAGIC_SYNCHRONIZED(magic_file_internal, &mga);
|
867
|
+
if (mga.status < 0 && !mga.result) {
|
767
868
|
/*
|
768
869
|
* Handle the case when the "ERROR" flag is set regardless of the
|
769
870
|
* current version of the underlying Magic library.
|
@@ -777,15 +878,15 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
777
878
|
* This is an attempt to mitigate the problem and correct it to achieve
|
778
879
|
* the desired behavior as per the standards.
|
779
880
|
*/
|
780
|
-
if (
|
781
|
-
MAGIC_LIBRARY_ERROR(
|
881
|
+
if (mgc->stop_on_errors || (mga.flags & MAGIC_ERROR))
|
882
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
782
883
|
|
783
|
-
|
884
|
+
mga.result = magic_error_wrapper(mgc->cookie);
|
784
885
|
}
|
785
|
-
if (!
|
886
|
+
if (!mga.result)
|
786
887
|
MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN);
|
787
888
|
|
788
|
-
assert(
|
889
|
+
assert(mga.result != NULL &&
|
789
890
|
"Must be a valid pointer to `const char' type");
|
790
891
|
|
791
892
|
/*
|
@@ -794,10 +895,10 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
794
895
|
* string instead. Often this would indicate that an older version of the
|
795
896
|
* Magic library is in use.
|
796
897
|
*/
|
797
|
-
assert(strncmp(
|
898
|
+
assert(strncmp(mga.result, empty, strlen(empty)) != 0 &&
|
798
899
|
"Empty or invalid result");
|
799
900
|
|
800
|
-
return magic_return(&
|
901
|
+
return magic_return(&mga);
|
801
902
|
error:
|
802
903
|
MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object");
|
803
904
|
}
|
@@ -811,28 +912,34 @@ error:
|
|
811
912
|
VALUE
|
812
913
|
rb_mgc_buffer(VALUE object, VALUE value)
|
813
914
|
{
|
814
|
-
|
815
|
-
|
915
|
+
rb_mgc_object_t *mgc;
|
916
|
+
rb_mgc_arguments_t mga;
|
816
917
|
|
817
918
|
MAGIC_CHECK_STRING_TYPE(value);
|
919
|
+
|
818
920
|
MAGIC_CHECK_OPEN(object);
|
819
921
|
MAGIC_CHECK_LOADED(object);
|
820
|
-
|
922
|
+
MAGIC_OBJECT(object, mgc);
|
821
923
|
|
822
924
|
StringValue(value);
|
823
925
|
|
824
|
-
|
825
|
-
|
826
|
-
|
926
|
+
mga = (rb_mgc_arguments_t) {
|
927
|
+
.magic_object = mgc,
|
928
|
+
.buffers = {
|
929
|
+
.pointers = (void **)RSTRING_PTR(value),
|
930
|
+
.sizes = (size_t *)RSTRING_LEN(value),
|
931
|
+
},
|
932
|
+
.flags = magic_get_flags(object),
|
933
|
+
};
|
827
934
|
|
828
|
-
MAGIC_SYNCHRONIZED(magic_buffer_internal, &
|
829
|
-
if (
|
830
|
-
MAGIC_LIBRARY_ERROR(
|
935
|
+
MAGIC_SYNCHRONIZED(magic_buffer_internal, &mga);
|
936
|
+
if (mga.status < 0)
|
937
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
831
938
|
|
832
|
-
assert(
|
939
|
+
assert(mga.result != NULL &&
|
833
940
|
"Must be a valid pointer to `const char' type");
|
834
941
|
|
835
|
-
return magic_return(&
|
942
|
+
return magic_return(&mga);
|
836
943
|
}
|
837
944
|
|
838
945
|
/*
|
@@ -846,34 +953,40 @@ VALUE
|
|
846
953
|
rb_mgc_descriptor(VALUE object, VALUE value)
|
847
954
|
{
|
848
955
|
int local_errno;
|
849
|
-
|
850
|
-
|
956
|
+
rb_mgc_object_t *mgc;
|
957
|
+
rb_mgc_arguments_t mga;
|
851
958
|
|
852
959
|
if (rb_respond_to(value, rb_intern("to_io")))
|
853
960
|
value = INT2NUM(magic_fileno(value));
|
854
961
|
|
855
962
|
MAGIC_CHECK_INTEGER_TYPE(value);
|
963
|
+
|
856
964
|
MAGIC_CHECK_OPEN(object);
|
857
965
|
MAGIC_CHECK_LOADED(object);
|
858
|
-
|
966
|
+
MAGIC_OBJECT(object, mgc);
|
859
967
|
|
860
|
-
|
861
|
-
|
968
|
+
mga = (rb_mgc_arguments_t) {
|
969
|
+
.magic_object = mgc,
|
970
|
+
.file = {
|
971
|
+
.fd = NUM2INT(value),
|
972
|
+
},
|
973
|
+
.flags = magic_get_flags(object),
|
974
|
+
};
|
862
975
|
|
863
|
-
MAGIC_SYNCHRONIZED(magic_descriptor_internal, &
|
976
|
+
MAGIC_SYNCHRONIZED(magic_descriptor_internal, &mga);
|
864
977
|
local_errno = errno;
|
865
978
|
|
866
|
-
if (
|
979
|
+
if (mga.status < 0) {
|
867
980
|
if (local_errno == EBADF)
|
868
981
|
rb_raise(rb_eIOError, "Bad file descriptor");
|
869
982
|
|
870
|
-
MAGIC_LIBRARY_ERROR(
|
983
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
871
984
|
}
|
872
985
|
|
873
|
-
assert(
|
986
|
+
assert(mga.result != NULL &&
|
874
987
|
"Must be a valid pointer to `const char' type");
|
875
988
|
|
876
|
-
return magic_return(&
|
989
|
+
return magic_return(&mga);
|
877
990
|
}
|
878
991
|
|
879
992
|
/*
|
@@ -895,59 +1008,69 @@ rb_mgc_version(RB_UNUSED_VAR(VALUE object))
|
|
895
1008
|
static inline void*
|
896
1009
|
nogvl_magic_load(void *data)
|
897
1010
|
{
|
898
|
-
|
1011
|
+
rb_mgc_arguments_t *mga = data;
|
1012
|
+
magic_t cookie = mga->magic_object->cookie;
|
1013
|
+
|
1014
|
+
mga->status = magic_load_wrapper(cookie,
|
1015
|
+
mga->file.path,
|
1016
|
+
mga->flags);
|
899
1017
|
|
900
|
-
ma->status = magic_load_wrapper(ma->cookie,
|
901
|
-
ma->type.file.path,
|
902
|
-
ma->flags);
|
903
1018
|
return NULL;
|
904
1019
|
}
|
905
1020
|
|
906
1021
|
static inline void*
|
907
1022
|
nogvl_magic_compile(void *data)
|
908
1023
|
{
|
909
|
-
|
1024
|
+
rb_mgc_arguments_t *mga = data;
|
1025
|
+
magic_t cookie = mga->magic_object->cookie;
|
1026
|
+
|
1027
|
+
mga->status = magic_compile_wrapper(cookie,
|
1028
|
+
mga->file.path,
|
1029
|
+
mga->flags);
|
910
1030
|
|
911
|
-
ma->status = magic_compile_wrapper(ma->cookie,
|
912
|
-
ma->type.file.path,
|
913
|
-
ma->flags);
|
914
1031
|
return NULL;
|
915
1032
|
}
|
916
1033
|
|
917
1034
|
static inline void*
|
918
1035
|
nogvl_magic_check(void *data)
|
919
1036
|
{
|
920
|
-
|
1037
|
+
rb_mgc_arguments_t *mga = data;
|
1038
|
+
magic_t cookie = mga->magic_object->cookie;
|
1039
|
+
|
1040
|
+
mga->status = magic_check_wrapper(cookie,
|
1041
|
+
mga->file.path,
|
1042
|
+
mga->flags);
|
921
1043
|
|
922
|
-
ma->status = magic_check_wrapper(ma->cookie,
|
923
|
-
ma->type.file.path,
|
924
|
-
ma->flags);
|
925
1044
|
return NULL;
|
926
1045
|
}
|
927
1046
|
|
928
1047
|
static inline void*
|
929
1048
|
nogvl_magic_file(void *data)
|
930
1049
|
{
|
931
|
-
|
1050
|
+
rb_mgc_arguments_t *mga = data;
|
1051
|
+
magic_t cookie = mga->magic_object->cookie;
|
932
1052
|
|
933
|
-
|
934
|
-
|
935
|
-
|
1053
|
+
mga->result = magic_file_wrapper(cookie,
|
1054
|
+
mga->file.path,
|
1055
|
+
mga->flags);
|
1056
|
+
|
1057
|
+
mga->status = !mga->result ? -1 : 0;
|
936
1058
|
|
937
|
-
ma->status = !ma->result ? -1 : 0;
|
938
1059
|
return NULL;
|
939
1060
|
}
|
940
1061
|
|
941
1062
|
static inline void*
|
942
1063
|
nogvl_magic_descriptor(void *data)
|
943
1064
|
{
|
944
|
-
|
1065
|
+
rb_mgc_arguments_t *mga = data;
|
1066
|
+
magic_t cookie = mga->magic_object->cookie;
|
1067
|
+
|
1068
|
+
mga->result = magic_descriptor_wrapper(cookie,
|
1069
|
+
mga->file.fd,
|
1070
|
+
mga->flags);
|
945
1071
|
|
946
|
-
|
947
|
-
ma->type.file.fd,
|
948
|
-
ma->flags);
|
1072
|
+
mga->status = !mga->result ? -1 : 0;
|
949
1073
|
|
950
|
-
ma->status = !ma->result ? -1 : 0;
|
951
1074
|
return NULL;
|
952
1075
|
}
|
953
1076
|
|
@@ -955,12 +1078,15 @@ static inline VALUE
|
|
955
1078
|
magic_get_parameter_internal(void *data)
|
956
1079
|
{
|
957
1080
|
size_t value;
|
958
|
-
|
1081
|
+
rb_mgc_arguments_t *mga = data;
|
1082
|
+
magic_t cookie = mga->magic_object->cookie;
|
1083
|
+
|
1084
|
+
mga->status = magic_getparam_wrapper(cookie,
|
1085
|
+
mga->parameter.tag,
|
1086
|
+
&value);
|
1087
|
+
|
1088
|
+
mga->parameter.value = value;
|
959
1089
|
|
960
|
-
ma->status = magic_getparam_wrapper(ma->cookie,
|
961
|
-
ma->type.parameter.tag,
|
962
|
-
&value);
|
963
|
-
ma->type.parameter.value = value;
|
964
1090
|
return (VALUE)NULL;
|
965
1091
|
}
|
966
1092
|
|
@@ -968,30 +1094,44 @@ static inline VALUE
|
|
968
1094
|
magic_set_parameter_internal(void *data)
|
969
1095
|
{
|
970
1096
|
size_t value;
|
971
|
-
|
1097
|
+
rb_mgc_arguments_t *mga = data;
|
1098
|
+
magic_t cookie = mga->magic_object->cookie;
|
1099
|
+
|
1100
|
+
value = mga->parameter.value;
|
1101
|
+
|
1102
|
+
mga->status = magic_setparam_wrapper(cookie,
|
1103
|
+
mga->parameter.tag,
|
1104
|
+
&value);
|
972
1105
|
|
973
|
-
value = ma->type.parameter.value;
|
974
|
-
ma->status = magic_setparam_wrapper(ma->cookie,
|
975
|
-
ma->type.parameter.tag,
|
976
|
-
&value);
|
977
1106
|
return (VALUE)NULL;
|
978
1107
|
}
|
979
1108
|
|
980
1109
|
static inline VALUE
|
981
1110
|
magic_get_flags_internal(void *data)
|
982
1111
|
{
|
983
|
-
|
1112
|
+
int flags;
|
1113
|
+
rb_mgc_arguments_t *mga = data;
|
1114
|
+
magic_t cookie = mga->magic_object->cookie;
|
1115
|
+
|
1116
|
+
mga->status = 0;
|
1117
|
+
|
1118
|
+
flags = magic_getflags_wrapper(cookie);
|
1119
|
+
if (flags < 0)
|
1120
|
+
mga->status = -1;
|
1121
|
+
else
|
1122
|
+
mga->flags = flags;
|
984
1123
|
|
985
|
-
ma->flags = magic_getflags_wrapper(ma->cookie);
|
986
1124
|
return (VALUE)NULL;
|
987
1125
|
}
|
988
1126
|
|
989
1127
|
static inline VALUE
|
990
1128
|
magic_set_flags_internal(void *data)
|
991
1129
|
{
|
992
|
-
|
1130
|
+
rb_mgc_arguments_t *mga = data;
|
1131
|
+
magic_t cookie = mga->magic_object->cookie;
|
1132
|
+
|
1133
|
+
mga->status = magic_setflags_wrapper(cookie, mga->flags);
|
993
1134
|
|
994
|
-
ma->status = magic_setflags_wrapper(ma->cookie, ma->flags);
|
995
1135
|
return (VALUE)NULL;
|
996
1136
|
}
|
997
1137
|
|
@@ -999,18 +1139,21 @@ static inline VALUE
|
|
999
1139
|
magic_close_internal(void *data)
|
1000
1140
|
{
|
1001
1141
|
magic_library_close(data);
|
1142
|
+
|
1002
1143
|
return Qnil;
|
1003
1144
|
}
|
1004
1145
|
|
1005
1146
|
static inline VALUE
|
1006
1147
|
magic_load_internal(void *data)
|
1007
1148
|
{
|
1008
|
-
|
1009
|
-
|
1149
|
+
rb_mgc_arguments_t *mga = data;
|
1150
|
+
magic_t cookie = mga->magic_object->cookie;
|
1151
|
+
int old_flags = mga->flags;
|
1152
|
+
|
1153
|
+
NOGVL(nogvl_magic_load, mga);
|
1010
1154
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
magic_setflags_wrapper(ma->cookie, old_flags);
|
1155
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1156
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1014
1157
|
|
1015
1158
|
return (VALUE)NULL;
|
1016
1159
|
}
|
@@ -1018,25 +1161,29 @@ magic_load_internal(void *data)
|
|
1018
1161
|
static inline VALUE
|
1019
1162
|
magic_load_buffers_internal(void *data)
|
1020
1163
|
{
|
1021
|
-
|
1164
|
+
rb_mgc_arguments_t *mga = data;
|
1165
|
+
magic_t cookie = mga->magic_object->cookie;
|
1166
|
+
|
1167
|
+
mga->status = magic_load_buffers_wrapper(cookie,
|
1168
|
+
mga->buffers.pointers,
|
1169
|
+
mga->buffers.sizes,
|
1170
|
+
mga->buffers.count,
|
1171
|
+
mga->flags);
|
1022
1172
|
|
1023
|
-
ma->status = magic_load_buffers_wrapper(ma->cookie,
|
1024
|
-
ma->type.buffers.pointers,
|
1025
|
-
ma->type.buffers.sizes,
|
1026
|
-
ma->type.buffers.count,
|
1027
|
-
ma->flags);
|
1028
1173
|
return (VALUE)NULL;
|
1029
1174
|
}
|
1030
1175
|
|
1031
1176
|
static inline VALUE
|
1032
1177
|
magic_compile_internal(void *data)
|
1033
1178
|
{
|
1034
|
-
|
1035
|
-
|
1179
|
+
rb_mgc_arguments_t *mga = data;
|
1180
|
+
magic_t cookie = mga->magic_object->cookie;
|
1181
|
+
int old_flags = mga->flags;
|
1036
1182
|
|
1037
|
-
NOGVL(nogvl_magic_compile,
|
1038
|
-
|
1039
|
-
|
1183
|
+
NOGVL(nogvl_magic_compile, mga);
|
1184
|
+
|
1185
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1186
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1040
1187
|
|
1041
1188
|
return (VALUE)NULL;
|
1042
1189
|
}
|
@@ -1044,12 +1191,14 @@ magic_compile_internal(void *data)
|
|
1044
1191
|
static inline VALUE
|
1045
1192
|
magic_check_internal(void *data)
|
1046
1193
|
{
|
1047
|
-
|
1048
|
-
|
1194
|
+
rb_mgc_arguments_t *mga = data;
|
1195
|
+
magic_t cookie = mga->magic_object->cookie;
|
1196
|
+
int old_flags = mga->flags;
|
1197
|
+
|
1198
|
+
NOGVL(nogvl_magic_check, mga);
|
1049
1199
|
|
1050
|
-
|
1051
|
-
|
1052
|
-
magic_setflags_wrapper(ma->cookie, old_flags);
|
1200
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1201
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1053
1202
|
|
1054
1203
|
return (VALUE)NULL;
|
1055
1204
|
}
|
@@ -1057,23 +1206,26 @@ magic_check_internal(void *data)
|
|
1057
1206
|
static VALUE
|
1058
1207
|
magic_file_internal(void *data)
|
1059
1208
|
{
|
1060
|
-
magic_arguments_t *ma = data;
|
1061
|
-
int old_flags = ma->flags;
|
1062
|
-
int restore_flags;
|
1063
1209
|
int local_errno;
|
1210
|
+
int restore_flags = 0;
|
1211
|
+
rb_mgc_arguments_t *mga = data;
|
1212
|
+
rb_mgc_object_t *mgc = mga->magic_object;
|
1213
|
+
magic_t cookie = mgc->cookie;
|
1214
|
+
int old_flags = mga->flags;
|
1064
1215
|
|
1065
|
-
if (
|
1066
|
-
|
1216
|
+
if (mgc->stop_on_errors)
|
1217
|
+
mga->flags |= MAGIC_ERROR;
|
1067
1218
|
|
1068
|
-
if (
|
1069
|
-
|
1219
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1220
|
+
mga->flags |= MAGIC_RAW;
|
1070
1221
|
|
1071
|
-
|
1222
|
+
if (old_flags != mga->flags)
|
1223
|
+
restore_flags = 1;
|
1072
1224
|
|
1073
1225
|
if (restore_flags)
|
1074
|
-
magic_setflags_wrapper(
|
1226
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1075
1227
|
|
1076
|
-
NOGVL(nogvl_magic_file,
|
1228
|
+
NOGVL(nogvl_magic_file, mga);
|
1077
1229
|
local_errno = errno;
|
1078
1230
|
/*
|
1079
1231
|
* The Magic library often does not correctly report errors,
|
@@ -1082,11 +1234,11 @@ magic_file_internal(void *data)
|
|
1082
1234
|
* Magic library itself, and if that does not work, then from
|
1083
1235
|
* the saved errno value.
|
1084
1236
|
*/
|
1085
|
-
if (magic_errno_wrapper(
|
1086
|
-
|
1237
|
+
if (magic_errno_wrapper(cookie) || local_errno)
|
1238
|
+
mga->status = -1;
|
1087
1239
|
|
1088
1240
|
if (restore_flags)
|
1089
|
-
magic_setflags_wrapper(
|
1241
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1090
1242
|
|
1091
1243
|
return (VALUE)NULL;
|
1092
1244
|
}
|
@@ -1094,27 +1246,29 @@ magic_file_internal(void *data)
|
|
1094
1246
|
static VALUE
|
1095
1247
|
magic_buffer_internal(void *data)
|
1096
1248
|
{
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1249
|
+
int restore_flags = 0;
|
1250
|
+
rb_mgc_arguments_t *mga = data;
|
1251
|
+
magic_t cookie = mga->magic_object->cookie;
|
1252
|
+
int old_flags = mga->flags;
|
1100
1253
|
|
1101
|
-
if (
|
1102
|
-
|
1254
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1255
|
+
mga->flags |= MAGIC_RAW;
|
1103
1256
|
|
1104
|
-
|
1257
|
+
if (old_flags != mga->flags)
|
1258
|
+
restore_flags = 1;
|
1105
1259
|
|
1106
1260
|
if (restore_flags)
|
1107
|
-
magic_setflags_wrapper(
|
1261
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1108
1262
|
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1263
|
+
mga->result = magic_buffer_wrapper(cookie,
|
1264
|
+
(const void *)mga->buffers.pointers,
|
1265
|
+
(size_t)mga->buffers.sizes,
|
1266
|
+
mga->flags);
|
1113
1267
|
|
1114
|
-
|
1268
|
+
mga->status = !mga->result ? -1 : 0;
|
1115
1269
|
|
1116
1270
|
if (restore_flags)
|
1117
|
-
magic_setflags_wrapper(
|
1271
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1118
1272
|
|
1119
1273
|
return (VALUE)NULL;
|
1120
1274
|
}
|
@@ -1122,128 +1276,168 @@ magic_buffer_internal(void *data)
|
|
1122
1276
|
static VALUE
|
1123
1277
|
magic_descriptor_internal(void *data)
|
1124
1278
|
{
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1279
|
+
int restore_flags = 0;
|
1280
|
+
rb_mgc_arguments_t *mga = data;
|
1281
|
+
magic_t cookie = mga->magic_object->cookie;
|
1282
|
+
int old_flags = mga->flags;
|
1128
1283
|
|
1129
|
-
if (
|
1130
|
-
|
1284
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1285
|
+
mga->flags |= MAGIC_RAW;
|
1131
1286
|
|
1132
|
-
|
1287
|
+
if (old_flags != mga->flags)
|
1288
|
+
restore_flags = 1;
|
1133
1289
|
|
1134
1290
|
if (restore_flags)
|
1135
|
-
magic_setflags_wrapper(
|
1291
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1136
1292
|
|
1137
|
-
NOGVL(nogvl_magic_descriptor,
|
1293
|
+
NOGVL(nogvl_magic_descriptor, mga);
|
1138
1294
|
|
1139
1295
|
if (restore_flags)
|
1140
|
-
magic_setflags_wrapper(
|
1296
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1141
1297
|
|
1142
1298
|
return (VALUE)NULL;
|
1143
1299
|
}
|
1144
1300
|
|
1301
|
+
static inline void*
|
1302
|
+
magic_library_open(void)
|
1303
|
+
{
|
1304
|
+
magic_t cookie;
|
1305
|
+
|
1306
|
+
cookie = magic_open_wrapper(MAGIC_NONE);
|
1307
|
+
if (!cookie) {
|
1308
|
+
errno = ENOMEM;
|
1309
|
+
return NULL;
|
1310
|
+
}
|
1311
|
+
|
1312
|
+
return cookie;
|
1313
|
+
}
|
1314
|
+
|
1315
|
+
static inline void
|
1316
|
+
magic_library_close(void *data)
|
1317
|
+
{
|
1318
|
+
rb_mgc_object_t *mgc = data;
|
1319
|
+
|
1320
|
+
assert(mgc != NULL &&
|
1321
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1322
|
+
|
1323
|
+
if (mgc->cookie)
|
1324
|
+
magic_close_wrapper(mgc->cookie);
|
1325
|
+
|
1326
|
+
mgc->cookie = NULL;
|
1327
|
+
}
|
1328
|
+
|
1145
1329
|
static VALUE
|
1146
1330
|
magic_allocate(VALUE klass)
|
1147
1331
|
{
|
1148
1332
|
int local_errno;
|
1149
|
-
|
1333
|
+
rb_mgc_object_t *mgc;
|
1150
1334
|
|
1151
|
-
|
1335
|
+
mgc = RB_ALLOC(rb_mgc_object_t);
|
1152
1336
|
local_errno = ENOMEM;
|
1153
1337
|
|
1154
|
-
if (!
|
1338
|
+
if (!mgc) {
|
1155
1339
|
errno = local_errno;
|
1156
1340
|
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1157
1341
|
local_errno,
|
1158
1342
|
E_NOT_ENOUGH_MEMORY);
|
1159
1343
|
}
|
1160
1344
|
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1345
|
+
mgc->cookie = NULL;
|
1346
|
+
mgc->mutex = Qundef;
|
1347
|
+
mgc->database_loaded = 0;
|
1348
|
+
mgc->stop_on_errors = 0;
|
1165
1349
|
|
1166
|
-
|
1167
|
-
local_errno =
|
1350
|
+
mgc->cookie = magic_library_open();
|
1351
|
+
local_errno = errno;
|
1168
1352
|
|
1169
|
-
if (!
|
1170
|
-
ruby_xfree(
|
1171
|
-
|
1353
|
+
if (!mgc->cookie) {
|
1354
|
+
ruby_xfree(mgc);
|
1355
|
+
mgc = NULL;
|
1172
1356
|
errno = local_errno;
|
1173
1357
|
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1174
1358
|
local_errno,
|
1175
1359
|
E_MAGIC_LIBRARY_INITIALIZE);
|
1176
1360
|
}
|
1177
1361
|
|
1178
|
-
return
|
1362
|
+
return TypedData_Wrap_Struct(klass, &rb_mgc_type, mgc);
|
1179
1363
|
}
|
1180
1364
|
|
1181
1365
|
static inline void
|
1182
|
-
|
1366
|
+
magic_mark(void *data)
|
1183
1367
|
{
|
1184
|
-
|
1368
|
+
rb_mgc_object_t *mgc = data;
|
1185
1369
|
|
1186
|
-
assert(
|
1187
|
-
"Must be a valid pointer to `
|
1370
|
+
assert(mgc != NULL &&
|
1371
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1188
1372
|
|
1189
|
-
|
1190
|
-
magic_close_wrapper(mo->cookie);
|
1191
|
-
|
1192
|
-
mo->cookie = NULL;
|
1373
|
+
MAGIC_GC_MARK(mgc->mutex);
|
1193
1374
|
}
|
1194
1375
|
|
1195
1376
|
static inline void
|
1196
|
-
|
1377
|
+
magic_free(void *data)
|
1197
1378
|
{
|
1198
|
-
|
1379
|
+
rb_mgc_object_t *mgc = data;
|
1199
1380
|
|
1200
|
-
assert(
|
1201
|
-
"Must be a valid pointer to `
|
1381
|
+
assert(mgc != NULL &&
|
1382
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1202
1383
|
|
1203
|
-
|
1384
|
+
if (mgc->cookie)
|
1385
|
+
magic_library_close(data);
|
1386
|
+
|
1387
|
+
mgc->cookie = NULL;
|
1388
|
+
mgc->mutex = Qundef;
|
1389
|
+
|
1390
|
+
ruby_xfree(mgc);
|
1204
1391
|
}
|
1205
1392
|
|
1206
|
-
static inline
|
1207
|
-
|
1393
|
+
static inline size_t
|
1394
|
+
magic_size(const void *data)
|
1208
1395
|
{
|
1209
|
-
|
1396
|
+
const rb_mgc_object_t *mgc = data;
|
1210
1397
|
|
1211
|
-
assert(
|
1212
|
-
"Must be a valid pointer to `
|
1398
|
+
assert(mgc != NULL &&
|
1399
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1213
1400
|
|
1214
|
-
|
1215
|
-
|
1401
|
+
return sizeof(*mgc);
|
1402
|
+
}
|
1216
1403
|
|
1217
|
-
|
1218
|
-
|
1404
|
+
#if defined(HAVE_RUBY_GC_COMPACT)
|
1405
|
+
static inline void
|
1406
|
+
magic_compact(void *data)
|
1407
|
+
{
|
1408
|
+
rb_mgc_object_t *mgc = data;
|
1409
|
+
|
1410
|
+
assert(mgc != NULL &&
|
1411
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1219
1412
|
|
1220
|
-
|
1413
|
+
mgc->mutex = rb_gc_location(mgc->mutex);
|
1221
1414
|
}
|
1415
|
+
#endif /* HAVE_RUBY_GC_COMPACT */
|
1222
1416
|
|
1223
1417
|
static inline VALUE
|
1224
1418
|
magic_exception_wrapper(VALUE value)
|
1225
1419
|
{
|
1226
|
-
|
1420
|
+
rb_mgc_error_t *mge = (rb_mgc_error_t *)value;
|
1227
1421
|
|
1228
|
-
return rb_exc_new2(
|
1422
|
+
return rb_exc_new2(mge->klass, mge->magic_error);
|
1229
1423
|
}
|
1230
1424
|
|
1231
1425
|
static VALUE
|
1232
1426
|
magic_exception(void *data)
|
1233
1427
|
{
|
1234
|
-
magic_exception_t *e = data;
|
1235
1428
|
int exception = 0;
|
1429
|
+
rb_mgc_error_t *mge = data;
|
1236
1430
|
VALUE object = Qundef;
|
1237
1431
|
|
1238
|
-
assert(
|
1239
|
-
"Must be a valid pointer to `
|
1432
|
+
assert(mge != NULL &&
|
1433
|
+
"Must be a valid pointer to `rb_mgc_error_t' type");
|
1240
1434
|
|
1241
|
-
object = rb_protect(magic_exception_wrapper, (VALUE)
|
1435
|
+
object = rb_protect(magic_exception_wrapper, (VALUE)mge, &exception);
|
1242
1436
|
|
1243
1437
|
if (exception)
|
1244
1438
|
rb_jump_tag(exception);
|
1245
1439
|
|
1246
|
-
rb_iv_set(object, "@errno", INT2NUM(
|
1440
|
+
rb_iv_set(object, "@errno", INT2NUM(mge->magic_errno));
|
1247
1441
|
RB_GC_GUARD(object);
|
1248
1442
|
|
1249
1443
|
return object;
|
@@ -1252,51 +1446,56 @@ magic_exception(void *data)
|
|
1252
1446
|
static inline VALUE
|
1253
1447
|
magic_generic_error(VALUE klass, int magic_errno, const char *magic_error)
|
1254
1448
|
{
|
1255
|
-
|
1449
|
+
rb_mgc_error_t mge;
|
1256
1450
|
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1451
|
+
mge = (rb_mgc_error_t) {
|
1452
|
+
.klass = klass,
|
1453
|
+
.magic_errno = magic_errno,
|
1454
|
+
.magic_error = magic_error,
|
1455
|
+
};
|
1260
1456
|
|
1261
|
-
return magic_exception(&
|
1457
|
+
return magic_exception(&mge);
|
1262
1458
|
}
|
1263
1459
|
|
1264
1460
|
static VALUE
|
1265
1461
|
magic_library_error(VALUE klass, void *data)
|
1266
1462
|
{
|
1267
|
-
|
1463
|
+
rb_mgc_error_t mge;
|
1268
1464
|
const char *message = NULL;
|
1269
1465
|
const char *empty = "(null)";
|
1270
1466
|
magic_t cookie = data;
|
1271
1467
|
|
1272
1468
|
UNUSED(empty);
|
1273
1469
|
|
1274
|
-
assert(cookie != NULL &&
|
1470
|
+
assert(cookie != NULL &&
|
1275
1471
|
"Must be a valid pointer to `magic_t' type");
|
1276
1472
|
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1473
|
+
mge = (rb_mgc_error_t) {
|
1474
|
+
.klass = klass,
|
1475
|
+
.magic_errno = -1,
|
1476
|
+
.magic_error = MAGIC_ERRORS(E_UNKNOWN),
|
1477
|
+
};
|
1280
1478
|
|
1281
1479
|
message = magic_error_wrapper(cookie);
|
1282
1480
|
if (message) {
|
1283
|
-
|
1284
|
-
|
1481
|
+
mge.magic_errno = magic_errno_wrapper(cookie);
|
1482
|
+
mge.magic_error = message;
|
1285
1483
|
}
|
1286
1484
|
|
1287
|
-
assert(strncmp(
|
1485
|
+
assert(strncmp(mge.magic_error, empty, strlen(empty)) != 0 &&
|
1288
1486
|
"Empty or invalid error message");
|
1289
1487
|
|
1290
|
-
return magic_exception(&
|
1488
|
+
return magic_exception(&mge);
|
1291
1489
|
}
|
1292
1490
|
|
1293
1491
|
VALUE
|
1294
1492
|
magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
|
1295
1493
|
{
|
1296
|
-
|
1494
|
+
rb_mgc_object_t *mgc;
|
1495
|
+
|
1496
|
+
MAGIC_OBJECT(object, mgc);
|
1297
1497
|
|
1298
|
-
|
1299
|
-
rb_funcall(mo->mutex, rb_intern("lock"), 0);
|
1498
|
+
rb_funcall(mgc->mutex, rb_intern("lock"), 0);
|
1300
1499
|
|
1301
1500
|
return rb_ensure(function, (VALUE)data, magic_unlock, object);
|
1302
1501
|
}
|
@@ -1304,10 +1503,11 @@ magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
|
|
1304
1503
|
VALUE
|
1305
1504
|
magic_unlock(VALUE object)
|
1306
1505
|
{
|
1307
|
-
|
1506
|
+
rb_mgc_object_t *mgc;
|
1308
1507
|
|
1309
|
-
MAGIC_OBJECT(
|
1310
|
-
|
1508
|
+
MAGIC_OBJECT(object, mgc);
|
1509
|
+
|
1510
|
+
rb_funcall(mgc->mutex, rb_intern("unlock"), 0);
|
1311
1511
|
|
1312
1512
|
return Qnil;
|
1313
1513
|
}
|
@@ -1315,13 +1515,12 @@ magic_unlock(VALUE object)
|
|
1315
1515
|
static VALUE
|
1316
1516
|
magic_return(void *data)
|
1317
1517
|
{
|
1318
|
-
|
1518
|
+
rb_mgc_arguments_t *mga = data;
|
1319
1519
|
const char *unknown = "???";
|
1320
1520
|
VALUE separator = Qundef;
|
1321
|
-
VALUE array
|
1322
|
-
VALUE string = Qundef;
|
1521
|
+
VALUE array, string;
|
1323
1522
|
|
1324
|
-
string = CSTR2RVAL(
|
1523
|
+
string = CSTR2RVAL(mga->result);
|
1325
1524
|
RB_GC_GUARD(string);
|
1326
1525
|
|
1327
1526
|
/*
|
@@ -1329,15 +1528,15 @@ magic_return(void *data)
|
|
1329
1528
|
* when the CONTINUE flag is set causing all valid matches found by the
|
1330
1529
|
* Magic library to be returned.
|
1331
1530
|
*/
|
1332
|
-
if (
|
1531
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1333
1532
|
separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR);
|
1334
1533
|
|
1335
|
-
if (
|
1534
|
+
if (mga->flags & MAGIC_EXTENSION) {
|
1336
1535
|
/*
|
1337
1536
|
* A possible I/O-related error has occurred, and there is very
|
1338
1537
|
* little sense processing the results, so return string as-is.
|
1339
1538
|
*/
|
1340
|
-
if (
|
1539
|
+
if (mga->status < 0)
|
1341
1540
|
return string;
|
1342
1541
|
/*
|
1343
1542
|
* A number of Magic flags that support primarily files e.g.,
|
@@ -1346,31 +1545,37 @@ magic_return(void *data)
|
|
1346
1545
|
* return an empty string, to indicate lack of results, rather
|
1347
1546
|
* than a confusing string consisting of three questions marks.
|
1348
1547
|
*/
|
1349
|
-
if (strncmp(
|
1548
|
+
if (strncmp(mga->result, unknown, strlen(unknown)) == 0)
|
1350
1549
|
return CSTR2RVAL("");
|
1351
1550
|
|
1352
1551
|
separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR);
|
1353
1552
|
}
|
1354
1553
|
|
1355
|
-
|
1554
|
+
RB_GC_GUARD(separator);
|
1555
|
+
|
1556
|
+
if (mga->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
|
1356
1557
|
array = magic_split(string, separator);
|
1357
1558
|
RB_GC_GUARD(array);
|
1358
|
-
|
1559
|
+
|
1560
|
+
if (RARRAY_LEN(array) > 1)
|
1561
|
+
return magic_strip_array(array);
|
1562
|
+
|
1563
|
+
string = magic_shift(array);
|
1359
1564
|
}
|
1360
1565
|
|
1361
|
-
return string;
|
1566
|
+
return magic_strip(string);
|
1362
1567
|
}
|
1363
1568
|
|
1364
1569
|
static inline int
|
1365
|
-
|
1570
|
+
magic_get_flags(VALUE object)
|
1366
1571
|
{
|
1367
1572
|
return NUM2INT(rb_ivar_get(object, id_at_flags));
|
1368
1573
|
}
|
1369
1574
|
|
1370
|
-
static inline
|
1371
|
-
magic_set_flags(VALUE object,
|
1575
|
+
static inline void
|
1576
|
+
magic_set_flags(VALUE object, int flags)
|
1372
1577
|
{
|
1373
|
-
|
1578
|
+
rb_ivar_set(object, id_at_flags, INT2NUM(flags));
|
1374
1579
|
}
|
1375
1580
|
|
1376
1581
|
static inline VALUE
|
@@ -1379,6 +1584,19 @@ magic_set_paths(VALUE object, VALUE value)
|
|
1379
1584
|
return rb_ivar_set(object, id_at_paths, value);
|
1380
1585
|
}
|
1381
1586
|
|
1587
|
+
static const rb_data_type_t rb_mgc_type = {
|
1588
|
+
.wrap_struct_name = "magic",
|
1589
|
+
.function = {
|
1590
|
+
.dmark = magic_mark,
|
1591
|
+
.dfree = magic_free,
|
1592
|
+
.dsize = magic_size,
|
1593
|
+
#if defined(HAVE_RUBY_GC_COMPACT)
|
1594
|
+
.dcompact = magic_compact,
|
1595
|
+
#endif /* HAVE_RUBY_GC_COMPACT */
|
1596
|
+
},
|
1597
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
1598
|
+
};
|
1599
|
+
|
1382
1600
|
void
|
1383
1601
|
Init_magic(void)
|
1384
1602
|
{
|