ruby-magic 0.3.0 → 0.5.0
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
- checksums.yaml.gz.sig +3 -0
- data/CONTRIBUTORS.md +16 -0
- data/NOTICE +39 -0
- data/README.md +9 -3
- data/dependencies.yml +22 -0
- data/ext/magic/common.h +52 -19
- data/ext/magic/extconf.rb +321 -45
- data/ext/magic/functions.c +40 -14
- data/ext/magic/functions.h +18 -12
- data/ext/magic/ruby-magic.c +575 -329
- data/ext/magic/ruby-magic.h +211 -103
- data/lib/magic/version.rb +1 -1
- data/lib/magic.rb +16 -1
- data.tar.gz.sig +0 -0
- metadata +47 -7
- metadata.gz.sig +0 -0
- data/VERSION +0 -1
data/ext/magic/ruby-magic.c
CHANGED
@@ -8,54 +8,71 @@ static int rb_mgc_do_not_auto_load;
|
|
8
8
|
static int rb_mgc_do_not_stop_on_error;
|
9
9
|
static int rb_mgc_warning;
|
10
10
|
|
11
|
-
ID id_at_flags;
|
12
|
-
ID id_at_paths;
|
11
|
+
static ID id_at_flags;
|
12
|
+
static ID id_at_paths;
|
13
13
|
|
14
|
-
VALUE rb_cMagic
|
14
|
+
static VALUE rb_cMagic;
|
15
15
|
|
16
|
-
VALUE rb_mgc_eError
|
17
|
-
VALUE rb_mgc_eMagicError
|
18
|
-
VALUE rb_mgc_eLibraryError
|
19
|
-
VALUE
|
20
|
-
VALUE
|
21
|
-
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
|
+
};
|
485
537
|
|
486
|
-
|
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);
|
487
550
|
|
488
|
-
|
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
|
+
}
|
555
|
+
|
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,16 +835,18 @@ 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
|
|
842
|
+
UNUSED(empty);
|
843
|
+
|
745
844
|
if (NIL_P(value))
|
746
845
|
goto error;
|
747
846
|
|
748
847
|
MAGIC_CHECK_OPEN(object);
|
749
848
|
MAGIC_CHECK_LOADED(object);
|
750
|
-
|
849
|
+
MAGIC_OBJECT(object, mgc);
|
751
850
|
|
752
851
|
if (rb_respond_to(value, rb_intern("to_io")))
|
753
852
|
return rb_mgc_descriptor(object, value);
|
@@ -756,12 +855,16 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
756
855
|
if (NIL_P(value))
|
757
856
|
goto error;
|
758
857
|
|
759
|
-
|
760
|
-
|
761
|
-
|
858
|
+
mga = (rb_mgc_arguments_t) {
|
859
|
+
.magic_object = mgc,
|
860
|
+
.file = {
|
861
|
+
.path = RVAL2CSTR(value),
|
862
|
+
},
|
863
|
+
.flags = magic_get_flags(object),
|
864
|
+
};
|
762
865
|
|
763
|
-
MAGIC_SYNCHRONIZED(magic_file_internal, &
|
764
|
-
if (!
|
866
|
+
MAGIC_SYNCHRONIZED(magic_file_internal, &mga);
|
867
|
+
if (mga.status < 0 && !mga.result) {
|
765
868
|
/*
|
766
869
|
* Handle the case when the "ERROR" flag is set regardless of the
|
767
870
|
* current version of the underlying Magic library.
|
@@ -775,15 +878,15 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
775
878
|
* This is an attempt to mitigate the problem and correct it to achieve
|
776
879
|
* the desired behavior as per the standards.
|
777
880
|
*/
|
778
|
-
if (
|
779
|
-
MAGIC_LIBRARY_ERROR(
|
780
|
-
|
781
|
-
|
881
|
+
if (mgc->stop_on_errors || (mga.flags & MAGIC_ERROR))
|
882
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
883
|
+
|
884
|
+
mga.result = magic_error_wrapper(mgc->cookie);
|
782
885
|
}
|
783
|
-
if (!
|
886
|
+
if (!mga.result)
|
784
887
|
MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN);
|
785
888
|
|
786
|
-
assert(
|
889
|
+
assert(mga.result != NULL &&
|
787
890
|
"Must be a valid pointer to `const char' type");
|
788
891
|
|
789
892
|
/*
|
@@ -792,10 +895,10 @@ rb_mgc_file(VALUE object, VALUE value)
|
|
792
895
|
* string instead. Often this would indicate that an older version of the
|
793
896
|
* Magic library is in use.
|
794
897
|
*/
|
795
|
-
assert(strncmp(
|
898
|
+
assert(strncmp(mga.result, empty, strlen(empty)) != 0 &&
|
796
899
|
"Empty or invalid result");
|
797
900
|
|
798
|
-
return magic_return(&
|
901
|
+
return magic_return(&mga);
|
799
902
|
error:
|
800
903
|
MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object");
|
801
904
|
}
|
@@ -809,28 +912,34 @@ error:
|
|
809
912
|
VALUE
|
810
913
|
rb_mgc_buffer(VALUE object, VALUE value)
|
811
914
|
{
|
812
|
-
|
813
|
-
|
915
|
+
rb_mgc_object_t *mgc;
|
916
|
+
rb_mgc_arguments_t mga;
|
814
917
|
|
815
918
|
MAGIC_CHECK_STRING_TYPE(value);
|
919
|
+
|
816
920
|
MAGIC_CHECK_OPEN(object);
|
817
921
|
MAGIC_CHECK_LOADED(object);
|
818
|
-
|
922
|
+
MAGIC_OBJECT(object, mgc);
|
819
923
|
|
820
924
|
StringValue(value);
|
821
925
|
|
822
|
-
|
823
|
-
|
824
|
-
|
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
|
+
};
|
825
934
|
|
826
|
-
MAGIC_SYNCHRONIZED(magic_buffer_internal, &
|
827
|
-
if (
|
828
|
-
MAGIC_LIBRARY_ERROR(
|
935
|
+
MAGIC_SYNCHRONIZED(magic_buffer_internal, &mga);
|
936
|
+
if (mga.status < 0)
|
937
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
829
938
|
|
830
|
-
assert(
|
939
|
+
assert(mga.result != NULL &&
|
831
940
|
"Must be a valid pointer to `const char' type");
|
832
941
|
|
833
|
-
return magic_return(&
|
942
|
+
return magic_return(&mga);
|
834
943
|
}
|
835
944
|
|
836
945
|
/*
|
@@ -844,34 +953,40 @@ VALUE
|
|
844
953
|
rb_mgc_descriptor(VALUE object, VALUE value)
|
845
954
|
{
|
846
955
|
int local_errno;
|
847
|
-
|
848
|
-
|
956
|
+
rb_mgc_object_t *mgc;
|
957
|
+
rb_mgc_arguments_t mga;
|
849
958
|
|
850
959
|
if (rb_respond_to(value, rb_intern("to_io")))
|
851
960
|
value = INT2NUM(magic_fileno(value));
|
852
961
|
|
853
962
|
MAGIC_CHECK_INTEGER_TYPE(value);
|
963
|
+
|
854
964
|
MAGIC_CHECK_OPEN(object);
|
855
965
|
MAGIC_CHECK_LOADED(object);
|
856
|
-
|
966
|
+
MAGIC_OBJECT(object, mgc);
|
857
967
|
|
858
|
-
|
859
|
-
|
968
|
+
mga = (rb_mgc_arguments_t) {
|
969
|
+
.magic_object = mgc,
|
970
|
+
.file = {
|
971
|
+
.fd = NUM2INT(value),
|
972
|
+
},
|
973
|
+
.flags = magic_get_flags(object),
|
974
|
+
};
|
860
975
|
|
861
|
-
MAGIC_SYNCHRONIZED(magic_descriptor_internal, &
|
976
|
+
MAGIC_SYNCHRONIZED(magic_descriptor_internal, &mga);
|
862
977
|
local_errno = errno;
|
863
978
|
|
864
|
-
if (
|
979
|
+
if (mga.status < 0) {
|
865
980
|
if (local_errno == EBADF)
|
866
981
|
rb_raise(rb_eIOError, "Bad file descriptor");
|
867
982
|
|
868
|
-
MAGIC_LIBRARY_ERROR(
|
983
|
+
MAGIC_LIBRARY_ERROR(mgc);
|
869
984
|
}
|
870
985
|
|
871
|
-
assert(
|
986
|
+
assert(mga.result != NULL &&
|
872
987
|
"Must be a valid pointer to `const char' type");
|
873
988
|
|
874
|
-
return magic_return(&
|
989
|
+
return magic_return(&mga);
|
875
990
|
}
|
876
991
|
|
877
992
|
/*
|
@@ -893,55 +1008,69 @@ rb_mgc_version(RB_UNUSED_VAR(VALUE object))
|
|
893
1008
|
static inline void*
|
894
1009
|
nogvl_magic_load(void *data)
|
895
1010
|
{
|
896
|
-
|
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);
|
897
1017
|
|
898
|
-
ma->status = magic_load_wrapper(ma->cookie,
|
899
|
-
ma->type.file.path,
|
900
|
-
ma->flags);
|
901
1018
|
return NULL;
|
902
1019
|
}
|
903
1020
|
|
904
1021
|
static inline void*
|
905
1022
|
nogvl_magic_compile(void *data)
|
906
1023
|
{
|
907
|
-
|
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);
|
908
1030
|
|
909
|
-
ma->status = magic_compile_wrapper(ma->cookie,
|
910
|
-
ma->type.file.path,
|
911
|
-
ma->flags);
|
912
1031
|
return NULL;
|
913
1032
|
}
|
914
1033
|
|
915
1034
|
static inline void*
|
916
1035
|
nogvl_magic_check(void *data)
|
917
1036
|
{
|
918
|
-
|
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);
|
919
1043
|
|
920
|
-
ma->status = magic_check_wrapper(ma->cookie,
|
921
|
-
ma->type.file.path,
|
922
|
-
ma->flags);
|
923
1044
|
return NULL;
|
924
1045
|
}
|
925
1046
|
|
926
1047
|
static inline void*
|
927
1048
|
nogvl_magic_file(void *data)
|
928
1049
|
{
|
929
|
-
|
1050
|
+
rb_mgc_arguments_t *mga = data;
|
1051
|
+
magic_t cookie = mga->magic_object->cookie;
|
1052
|
+
|
1053
|
+
mga->result = magic_file_wrapper(cookie,
|
1054
|
+
mga->file.path,
|
1055
|
+
mga->flags);
|
1056
|
+
|
1057
|
+
mga->status = !mga->result ? -1 : 0;
|
930
1058
|
|
931
|
-
ma->result = magic_file_wrapper(ma->cookie,
|
932
|
-
ma->type.file.path,
|
933
|
-
ma->flags);
|
934
1059
|
return NULL;
|
935
1060
|
}
|
936
1061
|
|
937
1062
|
static inline void*
|
938
1063
|
nogvl_magic_descriptor(void *data)
|
939
1064
|
{
|
940
|
-
|
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);
|
1071
|
+
|
1072
|
+
mga->status = !mga->result ? -1 : 0;
|
941
1073
|
|
942
|
-
ma->result = magic_descriptor_wrapper(ma->cookie,
|
943
|
-
ma->type.file.fd,
|
944
|
-
ma->flags);
|
945
1074
|
return NULL;
|
946
1075
|
}
|
947
1076
|
|
@@ -949,12 +1078,15 @@ static inline VALUE
|
|
949
1078
|
magic_get_parameter_internal(void *data)
|
950
1079
|
{
|
951
1080
|
size_t value;
|
952
|
-
|
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;
|
953
1089
|
|
954
|
-
ma->status = magic_getparam_wrapper(ma->cookie,
|
955
|
-
ma->type.parameter.tag,
|
956
|
-
&value);
|
957
|
-
ma->type.parameter.value = value;
|
958
1090
|
return (VALUE)NULL;
|
959
1091
|
}
|
960
1092
|
|
@@ -962,30 +1094,44 @@ static inline VALUE
|
|
962
1094
|
magic_set_parameter_internal(void *data)
|
963
1095
|
{
|
964
1096
|
size_t value;
|
965
|
-
|
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);
|
966
1105
|
|
967
|
-
value = ma->type.parameter.value;
|
968
|
-
ma->status = magic_setparam_wrapper(ma->cookie,
|
969
|
-
ma->type.parameter.tag,
|
970
|
-
&value);
|
971
1106
|
return (VALUE)NULL;
|
972
1107
|
}
|
973
1108
|
|
974
1109
|
static inline VALUE
|
975
1110
|
magic_get_flags_internal(void *data)
|
976
1111
|
{
|
977
|
-
|
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;
|
978
1123
|
|
979
|
-
ma->flags = magic_getflags_wrapper(ma->cookie);
|
980
1124
|
return (VALUE)NULL;
|
981
1125
|
}
|
982
1126
|
|
983
1127
|
static inline VALUE
|
984
1128
|
magic_set_flags_internal(void *data)
|
985
1129
|
{
|
986
|
-
|
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);
|
987
1134
|
|
988
|
-
ma->status = magic_setflags_wrapper(ma->cookie, ma->flags);
|
989
1135
|
return (VALUE)NULL;
|
990
1136
|
}
|
991
1137
|
|
@@ -993,62 +1139,93 @@ static inline VALUE
|
|
993
1139
|
magic_close_internal(void *data)
|
994
1140
|
{
|
995
1141
|
magic_library_close(data);
|
1142
|
+
|
996
1143
|
return Qnil;
|
997
1144
|
}
|
998
1145
|
|
999
1146
|
static inline VALUE
|
1000
1147
|
magic_load_internal(void *data)
|
1001
1148
|
{
|
1002
|
-
|
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);
|
1154
|
+
|
1155
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1156
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1157
|
+
|
1158
|
+
return (VALUE)NULL;
|
1003
1159
|
}
|
1004
1160
|
|
1005
1161
|
static inline VALUE
|
1006
1162
|
magic_load_buffers_internal(void *data)
|
1007
1163
|
{
|
1008
|
-
|
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);
|
1009
1172
|
|
1010
|
-
ma->status = magic_load_buffers_wrapper(ma->cookie,
|
1011
|
-
ma->type.buffers.pointers,
|
1012
|
-
ma->type.buffers.sizes,
|
1013
|
-
ma->type.buffers.count,
|
1014
|
-
ma->flags);
|
1015
1173
|
return (VALUE)NULL;
|
1016
1174
|
}
|
1017
1175
|
|
1018
1176
|
static inline VALUE
|
1019
1177
|
magic_compile_internal(void *data)
|
1020
1178
|
{
|
1021
|
-
|
1179
|
+
rb_mgc_arguments_t *mga = data;
|
1180
|
+
magic_t cookie = mga->magic_object->cookie;
|
1181
|
+
int old_flags = mga->flags;
|
1182
|
+
|
1183
|
+
NOGVL(nogvl_magic_compile, mga);
|
1184
|
+
|
1185
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1186
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1187
|
+
|
1188
|
+
return (VALUE)NULL;
|
1022
1189
|
}
|
1023
1190
|
|
1024
1191
|
static inline VALUE
|
1025
1192
|
magic_check_internal(void *data)
|
1026
1193
|
{
|
1027
|
-
|
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);
|
1199
|
+
|
1200
|
+
if (MAGIC_STATUS_CHECK(mga->status < 0))
|
1201
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1202
|
+
|
1203
|
+
return (VALUE)NULL;
|
1028
1204
|
}
|
1029
1205
|
|
1030
1206
|
static VALUE
|
1031
1207
|
magic_file_internal(void *data)
|
1032
1208
|
{
|
1033
1209
|
int local_errno;
|
1034
|
-
int old_flags = 0;
|
1035
1210
|
int restore_flags = 0;
|
1036
|
-
|
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;
|
1037
1215
|
|
1038
|
-
if (
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
ma->flags |= MAGIC_RAW;
|
1216
|
+
if (mgc->stop_on_errors)
|
1217
|
+
mga->flags |= MAGIC_ERROR;
|
1218
|
+
|
1219
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1220
|
+
mga->flags |= MAGIC_RAW;
|
1221
|
+
|
1222
|
+
if (old_flags != mga->flags)
|
1046
1223
|
restore_flags = 1;
|
1047
|
-
}
|
1048
|
-
if (restore_flags && ma->flags)
|
1049
|
-
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1050
1224
|
|
1051
|
-
|
1225
|
+
if (restore_flags)
|
1226
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1227
|
+
|
1228
|
+
NOGVL(nogvl_magic_file, mga);
|
1052
1229
|
local_errno = errno;
|
1053
1230
|
/*
|
1054
1231
|
* The Magic library often does not correctly report errors,
|
@@ -1057,13 +1234,11 @@ magic_file_internal(void *data)
|
|
1057
1234
|
* Magic library itself, and if that does not work, then from
|
1058
1235
|
* the saved errno value.
|
1059
1236
|
*/
|
1060
|
-
if (magic_errno_wrapper(
|
1061
|
-
|
1062
|
-
else if (local_errno)
|
1063
|
-
ma->status = -1;
|
1237
|
+
if (magic_errno_wrapper(cookie) || local_errno)
|
1238
|
+
mga->status = -1;
|
1064
1239
|
|
1065
|
-
if (restore_flags
|
1066
|
-
magic_setflags_wrapper(
|
1240
|
+
if (restore_flags)
|
1241
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1067
1242
|
|
1068
1243
|
return (VALUE)NULL;
|
1069
1244
|
}
|
@@ -1071,24 +1246,29 @@ magic_file_internal(void *data)
|
|
1071
1246
|
static VALUE
|
1072
1247
|
magic_buffer_internal(void *data)
|
1073
1248
|
{
|
1074
|
-
int old_flags = 0;
|
1075
1249
|
int restore_flags = 0;
|
1076
|
-
|
1250
|
+
rb_mgc_arguments_t *mga = data;
|
1251
|
+
magic_t cookie = mga->magic_object->cookie;
|
1252
|
+
int old_flags = mga->flags;
|
1253
|
+
|
1254
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1255
|
+
mga->flags |= MAGIC_RAW;
|
1077
1256
|
|
1078
|
-
if (
|
1079
|
-
old_flags = ma->flags;
|
1080
|
-
ma->flags |= MAGIC_RAW;
|
1257
|
+
if (old_flags != mga->flags)
|
1081
1258
|
restore_flags = 1;
|
1082
|
-
}
|
1083
|
-
if (restore_flags && ma->flags)
|
1084
|
-
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1085
1259
|
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1260
|
+
if (restore_flags)
|
1261
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1262
|
+
|
1263
|
+
mga->result = magic_buffer_wrapper(cookie,
|
1264
|
+
(const void *)mga->buffers.pointers,
|
1265
|
+
(size_t)mga->buffers.sizes,
|
1266
|
+
mga->flags);
|
1267
|
+
|
1268
|
+
mga->status = !mga->result ? -1 : 0;
|
1269
|
+
|
1270
|
+
if (restore_flags)
|
1271
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1092
1272
|
|
1093
1273
|
return (VALUE)NULL;
|
1094
1274
|
}
|
@@ -1096,128 +1276,168 @@ magic_buffer_internal(void *data)
|
|
1096
1276
|
static VALUE
|
1097
1277
|
magic_descriptor_internal(void *data)
|
1098
1278
|
{
|
1099
|
-
int old_flags = 0;
|
1100
1279
|
int restore_flags = 0;
|
1101
|
-
|
1280
|
+
rb_mgc_arguments_t *mga = data;
|
1281
|
+
magic_t cookie = mga->magic_object->cookie;
|
1282
|
+
int old_flags = mga->flags;
|
1102
1283
|
|
1103
|
-
if (
|
1104
|
-
|
1105
|
-
|
1284
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1285
|
+
mga->flags |= MAGIC_RAW;
|
1286
|
+
|
1287
|
+
if (old_flags != mga->flags)
|
1106
1288
|
restore_flags = 1;
|
1107
|
-
}
|
1108
|
-
if (restore_flags && ma->flags)
|
1109
|
-
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1110
1289
|
|
1111
|
-
|
1290
|
+
if (restore_flags)
|
1291
|
+
magic_setflags_wrapper(cookie, mga->flags);
|
1292
|
+
|
1293
|
+
NOGVL(nogvl_magic_descriptor, mga);
|
1112
1294
|
|
1113
|
-
if (restore_flags
|
1114
|
-
magic_setflags_wrapper(
|
1295
|
+
if (restore_flags)
|
1296
|
+
magic_setflags_wrapper(cookie, old_flags);
|
1115
1297
|
|
1116
1298
|
return (VALUE)NULL;
|
1117
1299
|
}
|
1118
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
|
+
|
1119
1329
|
static VALUE
|
1120
1330
|
magic_allocate(VALUE klass)
|
1121
1331
|
{
|
1122
1332
|
int local_errno;
|
1123
|
-
|
1333
|
+
rb_mgc_object_t *mgc;
|
1124
1334
|
|
1125
|
-
|
1335
|
+
mgc = RB_ALLOC(rb_mgc_object_t);
|
1126
1336
|
local_errno = ENOMEM;
|
1127
1337
|
|
1128
|
-
if (!
|
1338
|
+
if (!mgc) {
|
1129
1339
|
errno = local_errno;
|
1130
1340
|
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1131
1341
|
local_errno,
|
1132
1342
|
E_NOT_ENOUGH_MEMORY);
|
1133
1343
|
}
|
1134
1344
|
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1345
|
+
mgc->cookie = NULL;
|
1346
|
+
mgc->mutex = Qundef;
|
1347
|
+
mgc->database_loaded = 0;
|
1348
|
+
mgc->stop_on_errors = 0;
|
1139
1349
|
|
1140
|
-
|
1141
|
-
local_errno =
|
1350
|
+
mgc->cookie = magic_library_open();
|
1351
|
+
local_errno = errno;
|
1142
1352
|
|
1143
|
-
if (!
|
1144
|
-
ruby_xfree(
|
1145
|
-
|
1353
|
+
if (!mgc->cookie) {
|
1354
|
+
ruby_xfree(mgc);
|
1355
|
+
mgc = NULL;
|
1146
1356
|
errno = local_errno;
|
1147
1357
|
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1148
1358
|
local_errno,
|
1149
1359
|
E_MAGIC_LIBRARY_INITIALIZE);
|
1150
1360
|
}
|
1151
1361
|
|
1152
|
-
return
|
1362
|
+
return TypedData_Wrap_Struct(klass, &rb_mgc_type, mgc);
|
1153
1363
|
}
|
1154
1364
|
|
1155
1365
|
static inline void
|
1156
|
-
|
1366
|
+
magic_mark(void *data)
|
1157
1367
|
{
|
1158
|
-
|
1159
|
-
|
1160
|
-
assert(mo != NULL && \
|
1161
|
-
"Must be a valid pointer to `magic_object_t' type");
|
1368
|
+
rb_mgc_object_t *mgc = data;
|
1162
1369
|
|
1163
|
-
|
1164
|
-
|
1370
|
+
assert(mgc != NULL &&
|
1371
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1165
1372
|
|
1166
|
-
|
1373
|
+
MAGIC_GC_MARK(mgc->mutex);
|
1167
1374
|
}
|
1168
1375
|
|
1169
1376
|
static inline void
|
1170
|
-
|
1377
|
+
magic_free(void *data)
|
1171
1378
|
{
|
1172
|
-
|
1379
|
+
rb_mgc_object_t *mgc = data;
|
1173
1380
|
|
1174
|
-
assert(
|
1175
|
-
"Must be a valid pointer to `
|
1381
|
+
assert(mgc != NULL &&
|
1382
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1383
|
+
|
1384
|
+
if (mgc->cookie)
|
1385
|
+
magic_library_close(data);
|
1176
1386
|
|
1177
|
-
|
1387
|
+
mgc->cookie = NULL;
|
1388
|
+
mgc->mutex = Qundef;
|
1389
|
+
|
1390
|
+
ruby_xfree(mgc);
|
1178
1391
|
}
|
1179
1392
|
|
1180
|
-
static inline
|
1181
|
-
|
1393
|
+
static inline size_t
|
1394
|
+
magic_size(const void *data)
|
1182
1395
|
{
|
1183
|
-
|
1396
|
+
const rb_mgc_object_t *mgc = data;
|
1184
1397
|
|
1185
|
-
assert(
|
1186
|
-
"Must be a valid pointer to `
|
1398
|
+
assert(mgc != NULL &&
|
1399
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1187
1400
|
|
1188
|
-
|
1189
|
-
|
1401
|
+
return sizeof(*mgc);
|
1402
|
+
}
|
1190
1403
|
|
1191
|
-
|
1192
|
-
|
1404
|
+
#if defined(HAVE_RUBY_GC_COMPACT)
|
1405
|
+
static inline void
|
1406
|
+
magic_compact(void *data)
|
1407
|
+
{
|
1408
|
+
rb_mgc_object_t *mgc = data;
|
1193
1409
|
|
1194
|
-
|
1410
|
+
assert(mgc != NULL &&
|
1411
|
+
"Must be a valid pointer to `rb_mgc_object_t' type");
|
1412
|
+
|
1413
|
+
mgc->mutex = rb_gc_location(mgc->mutex);
|
1195
1414
|
}
|
1415
|
+
#endif /* HAVE_RUBY_GC_COMPACT */
|
1196
1416
|
|
1197
1417
|
static inline VALUE
|
1198
1418
|
magic_exception_wrapper(VALUE value)
|
1199
1419
|
{
|
1200
|
-
|
1420
|
+
rb_mgc_error_t *mge = (rb_mgc_error_t *)value;
|
1201
1421
|
|
1202
|
-
return rb_exc_new2(
|
1422
|
+
return rb_exc_new2(mge->klass, mge->magic_error);
|
1203
1423
|
}
|
1204
1424
|
|
1205
1425
|
static VALUE
|
1206
1426
|
magic_exception(void *data)
|
1207
1427
|
{
|
1208
|
-
magic_exception_t *e = data;
|
1209
1428
|
int exception = 0;
|
1429
|
+
rb_mgc_error_t *mge = data;
|
1210
1430
|
VALUE object = Qundef;
|
1211
1431
|
|
1212
|
-
assert(
|
1213
|
-
"Must be a valid pointer to `
|
1432
|
+
assert(mge != NULL &&
|
1433
|
+
"Must be a valid pointer to `rb_mgc_error_t' type");
|
1214
1434
|
|
1215
|
-
object = rb_protect(magic_exception_wrapper, (VALUE)
|
1435
|
+
object = rb_protect(magic_exception_wrapper, (VALUE)mge, &exception);
|
1216
1436
|
|
1217
1437
|
if (exception)
|
1218
1438
|
rb_jump_tag(exception);
|
1219
1439
|
|
1220
|
-
rb_iv_set(object, "@errno", INT2NUM(
|
1440
|
+
rb_iv_set(object, "@errno", INT2NUM(mge->magic_errno));
|
1221
1441
|
RB_GC_GUARD(object);
|
1222
1442
|
|
1223
1443
|
return object;
|
@@ -1226,49 +1446,56 @@ magic_exception(void *data)
|
|
1226
1446
|
static inline VALUE
|
1227
1447
|
magic_generic_error(VALUE klass, int magic_errno, const char *magic_error)
|
1228
1448
|
{
|
1229
|
-
|
1449
|
+
rb_mgc_error_t mge;
|
1230
1450
|
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1451
|
+
mge = (rb_mgc_error_t) {
|
1452
|
+
.klass = klass,
|
1453
|
+
.magic_errno = magic_errno,
|
1454
|
+
.magic_error = magic_error,
|
1455
|
+
};
|
1234
1456
|
|
1235
|
-
return magic_exception(&
|
1457
|
+
return magic_exception(&mge);
|
1236
1458
|
}
|
1237
1459
|
|
1238
1460
|
static VALUE
|
1239
1461
|
magic_library_error(VALUE klass, void *data)
|
1240
1462
|
{
|
1241
|
-
|
1463
|
+
rb_mgc_error_t mge;
|
1242
1464
|
const char *message = NULL;
|
1243
1465
|
const char *empty = "(null)";
|
1244
1466
|
magic_t cookie = data;
|
1245
1467
|
|
1246
|
-
|
1468
|
+
UNUSED(empty);
|
1469
|
+
|
1470
|
+
assert(cookie != NULL &&
|
1247
1471
|
"Must be a valid pointer to `magic_t' type");
|
1248
1472
|
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1473
|
+
mge = (rb_mgc_error_t) {
|
1474
|
+
.klass = klass,
|
1475
|
+
.magic_errno = -1,
|
1476
|
+
.magic_error = MAGIC_ERRORS(E_UNKNOWN),
|
1477
|
+
};
|
1252
1478
|
|
1253
1479
|
message = magic_error_wrapper(cookie);
|
1254
1480
|
if (message) {
|
1255
|
-
|
1256
|
-
|
1481
|
+
mge.magic_errno = magic_errno_wrapper(cookie);
|
1482
|
+
mge.magic_error = message;
|
1257
1483
|
}
|
1258
1484
|
|
1259
|
-
assert(strncmp(
|
1485
|
+
assert(strncmp(mge.magic_error, empty, strlen(empty)) != 0 &&
|
1260
1486
|
"Empty or invalid error message");
|
1261
1487
|
|
1262
|
-
return magic_exception(&
|
1488
|
+
return magic_exception(&mge);
|
1263
1489
|
}
|
1264
1490
|
|
1265
1491
|
VALUE
|
1266
1492
|
magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
|
1267
1493
|
{
|
1268
|
-
|
1494
|
+
rb_mgc_object_t *mgc;
|
1269
1495
|
|
1270
|
-
MAGIC_OBJECT(
|
1271
|
-
|
1496
|
+
MAGIC_OBJECT(object, mgc);
|
1497
|
+
|
1498
|
+
rb_funcall(mgc->mutex, rb_intern("lock"), 0);
|
1272
1499
|
|
1273
1500
|
return rb_ensure(function, (VALUE)data, magic_unlock, object);
|
1274
1501
|
}
|
@@ -1276,10 +1503,11 @@ magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
|
|
1276
1503
|
VALUE
|
1277
1504
|
magic_unlock(VALUE object)
|
1278
1505
|
{
|
1279
|
-
|
1506
|
+
rb_mgc_object_t *mgc;
|
1507
|
+
|
1508
|
+
MAGIC_OBJECT(object, mgc);
|
1280
1509
|
|
1281
|
-
|
1282
|
-
rb_funcall(mo->mutex, rb_intern("unlock"), 0, Qundef);
|
1510
|
+
rb_funcall(mgc->mutex, rb_intern("unlock"), 0);
|
1283
1511
|
|
1284
1512
|
return Qnil;
|
1285
1513
|
}
|
@@ -1287,13 +1515,12 @@ magic_unlock(VALUE object)
|
|
1287
1515
|
static VALUE
|
1288
1516
|
magic_return(void *data)
|
1289
1517
|
{
|
1290
|
-
|
1518
|
+
rb_mgc_arguments_t *mga = data;
|
1291
1519
|
const char *unknown = "???";
|
1292
1520
|
VALUE separator = Qundef;
|
1293
|
-
VALUE array
|
1294
|
-
VALUE string = Qundef;
|
1521
|
+
VALUE array, string;
|
1295
1522
|
|
1296
|
-
string = CSTR2RVAL(
|
1523
|
+
string = CSTR2RVAL(mga->result);
|
1297
1524
|
RB_GC_GUARD(string);
|
1298
1525
|
|
1299
1526
|
/*
|
@@ -1301,15 +1528,15 @@ magic_return(void *data)
|
|
1301
1528
|
* when the CONTINUE flag is set causing all valid matches found by the
|
1302
1529
|
* Magic library to be returned.
|
1303
1530
|
*/
|
1304
|
-
if (
|
1531
|
+
if (mga->flags & MAGIC_CONTINUE)
|
1305
1532
|
separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR);
|
1306
1533
|
|
1307
|
-
if (
|
1534
|
+
if (mga->flags & MAGIC_EXTENSION) {
|
1308
1535
|
/*
|
1309
1536
|
* A possible I/O-related error has occurred, and there is very
|
1310
1537
|
* little sense processing the results, so return string as-is.
|
1311
1538
|
*/
|
1312
|
-
if (
|
1539
|
+
if (mga->status < 0)
|
1313
1540
|
return string;
|
1314
1541
|
/*
|
1315
1542
|
* A number of Magic flags that support primarily files e.g.,
|
@@ -1318,31 +1545,37 @@ magic_return(void *data)
|
|
1318
1545
|
* return an empty string, to indicate lack of results, rather
|
1319
1546
|
* than a confusing string consisting of three questions marks.
|
1320
1547
|
*/
|
1321
|
-
if (strncmp(
|
1548
|
+
if (strncmp(mga->result, unknown, strlen(unknown)) == 0)
|
1322
1549
|
return CSTR2RVAL("");
|
1323
1550
|
|
1324
1551
|
separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR);
|
1325
1552
|
}
|
1326
1553
|
|
1327
|
-
|
1554
|
+
RB_GC_GUARD(separator);
|
1555
|
+
|
1556
|
+
if (mga->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
|
1328
1557
|
array = magic_split(string, separator);
|
1329
1558
|
RB_GC_GUARD(array);
|
1330
|
-
|
1559
|
+
|
1560
|
+
if (RARRAY_LEN(array) > 1)
|
1561
|
+
return magic_strip_array(array);
|
1562
|
+
|
1563
|
+
string = magic_shift(array);
|
1331
1564
|
}
|
1332
1565
|
|
1333
|
-
return string;
|
1566
|
+
return magic_strip(string);
|
1334
1567
|
}
|
1335
1568
|
|
1336
1569
|
static inline int
|
1337
|
-
|
1570
|
+
magic_get_flags(VALUE object)
|
1338
1571
|
{
|
1339
1572
|
return NUM2INT(rb_ivar_get(object, id_at_flags));
|
1340
1573
|
}
|
1341
1574
|
|
1342
|
-
static inline
|
1343
|
-
magic_set_flags(VALUE object,
|
1575
|
+
static inline void
|
1576
|
+
magic_set_flags(VALUE object, int flags)
|
1344
1577
|
{
|
1345
|
-
|
1578
|
+
rb_ivar_set(object, id_at_flags, INT2NUM(flags));
|
1346
1579
|
}
|
1347
1580
|
|
1348
1581
|
static inline VALUE
|
@@ -1351,6 +1584,19 @@ magic_set_paths(VALUE object, VALUE value)
|
|
1351
1584
|
return rb_ivar_set(object, id_at_paths, value);
|
1352
1585
|
}
|
1353
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
|
+
|
1354
1600
|
void
|
1355
1601
|
Init_magic(void)
|
1356
1602
|
{
|