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