ruby-magic-static 0.3.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 +7 -0
- data/AUTHORS +1 -0
- data/CHANGELOG.md +60 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +202 -0
- data/NOTICE +466 -0
- data/README.md +46 -0
- data/VERSION +1 -0
- data/ext/magic/common.h +132 -0
- data/ext/magic/extconf.rb +196 -0
- data/ext/magic/functions.c +344 -0
- data/ext/magic/functions.h +67 -0
- data/ext/magic/ruby-magic.c +1595 -0
- data/ext/magic/ruby-magic.h +307 -0
- data/kwilczynski-public.pem +25 -0
- data/lib/magic.rb +203 -0
- data/lib/magic/core/file.rb +66 -0
- data/lib/magic/core/string.rb +33 -0
- data/lib/magic/version.rb +42 -0
- metadata +73 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
#if !defined(_FUNCTIONS_H)
|
2
|
+
#define _FUNCTIONS_H 1
|
3
|
+
|
4
|
+
#if defined(__cplusplus)
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#include "common.h"
|
9
|
+
|
10
|
+
#define MAGIC_FUNCTION(f, r, x, ...) \
|
11
|
+
do { \
|
12
|
+
if ((x) & MAGIC_DEBUG) \
|
13
|
+
r = f(__VA_ARGS__); \
|
14
|
+
else { \
|
15
|
+
save_t __##f; \
|
16
|
+
override_error_output(&(__##f)); \
|
17
|
+
r = f(__VA_ARGS__); \
|
18
|
+
restore_error_output(&(__##f)); \
|
19
|
+
} \
|
20
|
+
} while(0)
|
21
|
+
|
22
|
+
typedef struct file_data {
|
23
|
+
fpos_t position;
|
24
|
+
int old_fd;
|
25
|
+
int new_fd;
|
26
|
+
} file_data_t;
|
27
|
+
|
28
|
+
typedef struct save {
|
29
|
+
file_data_t file;
|
30
|
+
int status;
|
31
|
+
} save_t;
|
32
|
+
|
33
|
+
extern magic_t magic_open_wrapper(int flags);
|
34
|
+
extern void magic_close_wrapper(magic_t magic);
|
35
|
+
|
36
|
+
extern const char* magic_error_wrapper(magic_t magic);
|
37
|
+
extern int magic_errno_wrapper(magic_t magic);
|
38
|
+
|
39
|
+
extern const char* magic_getpath_wrapper(void);
|
40
|
+
|
41
|
+
extern int magic_getparam_wrapper(magic_t magic, int parameter, void *value);
|
42
|
+
extern int magic_setparam_wrapper(magic_t magic, int parameter,
|
43
|
+
const void *value);
|
44
|
+
|
45
|
+
extern int magic_getflags_wrapper(magic_t magic);
|
46
|
+
extern int magic_setflags_wrapper(magic_t magic, int flags);
|
47
|
+
|
48
|
+
extern int magic_load_wrapper(magic_t magic, const char *magic_file, int flags);
|
49
|
+
extern int magic_load_buffers_wrapper(magic_t magic, void **buffers,
|
50
|
+
size_t *sizes, size_t count, int flags);
|
51
|
+
|
52
|
+
extern int magic_compile_wrapper(magic_t magic, const char *magic_file, int flags);
|
53
|
+
extern int magic_check_wrapper(magic_t magic, const char *magic_file, int flags);
|
54
|
+
|
55
|
+
extern const char* magic_file_wrapper(magic_t magic, const char *filename,
|
56
|
+
int flags);
|
57
|
+
extern const char* magic_buffer_wrapper(magic_t magic, const void *buffer,
|
58
|
+
size_t size, int flags);
|
59
|
+
extern const char* magic_descriptor_wrapper(magic_t magic, int fd, int flags);
|
60
|
+
|
61
|
+
extern int magic_version_wrapper(void);
|
62
|
+
|
63
|
+
#if defined(__cplusplus)
|
64
|
+
}
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#endif /* _FUNCTIONS_H */
|
@@ -0,0 +1,1595 @@
|
|
1
|
+
#if defined(__cplusplus)
|
2
|
+
extern "C" {
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#include "ruby-magic.h"
|
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
|
+
ID id_at_flags;
|
12
|
+
ID id_at_paths;
|
13
|
+
|
14
|
+
VALUE rb_cMagic = Qundef;
|
15
|
+
|
16
|
+
VALUE rb_mgc_eError = Qundef;
|
17
|
+
VALUE rb_mgc_eMagicError = Qundef;
|
18
|
+
VALUE rb_mgc_eLibraryError = Qundef;
|
19
|
+
VALUE rb_mgc_eParameterError = Qundef;
|
20
|
+
VALUE rb_mgc_eFlagsError = Qundef;
|
21
|
+
VALUE rb_mgc_eNotImplementedError = Qundef;
|
22
|
+
|
23
|
+
void Init_magic(void);
|
24
|
+
|
25
|
+
static VALUE magic_get_parameter_internal(void *data);
|
26
|
+
static VALUE magic_set_parameter_internal(void *data);
|
27
|
+
static VALUE magic_get_flags_internal(void *data);
|
28
|
+
static VALUE magic_set_flags_internal(void *data);
|
29
|
+
static VALUE magic_load_internal(void *data);
|
30
|
+
static VALUE magic_load_buffers_internal(void *data);
|
31
|
+
static VALUE magic_compile_internal(void *data);
|
32
|
+
static VALUE magic_check_internal(void *data);
|
33
|
+
static VALUE magic_file_internal(void *data);
|
34
|
+
static VALUE magic_buffer_internal(void *data);
|
35
|
+
static VALUE magic_descriptor_internal(void *data);
|
36
|
+
static VALUE magic_close_internal(void *data);
|
37
|
+
|
38
|
+
static void* nogvl_magic_load(void *data);
|
39
|
+
static void* nogvl_magic_compile(void *data);
|
40
|
+
static void* nogvl_magic_check(void *data);
|
41
|
+
static void* nogvl_magic_file(void *data);
|
42
|
+
static void* nogvl_magic_descriptor(void *data);
|
43
|
+
|
44
|
+
static VALUE magic_allocate(VALUE klass);
|
45
|
+
static void magic_mark(void *data);
|
46
|
+
static void magic_free(void *data);
|
47
|
+
static VALUE magic_exception_wrapper(VALUE value);
|
48
|
+
static VALUE magic_exception(void *data);
|
49
|
+
static void magic_library_close(void *data);
|
50
|
+
static VALUE magic_library_error(VALUE klass, void *data);
|
51
|
+
static VALUE magic_generic_error(VALUE klass, int magic_errno,
|
52
|
+
const char *magic_error);
|
53
|
+
static VALUE magic_lock(VALUE object, VALUE (*function)(ANYARGS),
|
54
|
+
void *data);
|
55
|
+
static VALUE magic_unlock(VALUE object);
|
56
|
+
static VALUE magic_return(void *data);
|
57
|
+
static int magic_flags(VALUE object);
|
58
|
+
static int magic_set_flags(VALUE object, VALUE value);
|
59
|
+
static VALUE magic_set_paths(VALUE object, VALUE value);
|
60
|
+
|
61
|
+
/*
|
62
|
+
* call-seq:
|
63
|
+
* Magic.do_not_auto_load -> boolean
|
64
|
+
*
|
65
|
+
* Returns +true+ if the global +do_not_auto_load+ flag is set, or +false+
|
66
|
+
* otherwise.
|
67
|
+
*
|
68
|
+
* Example:
|
69
|
+
*
|
70
|
+
* Magic.do_not_auto_load #=> false
|
71
|
+
* Magic.do_not_auto_load = true #=> true
|
72
|
+
* Magic.do_not_auto_load #=> true
|
73
|
+
*
|
74
|
+
* See also: Magic::new, Magic#loaded?, Magic#load and Magic#load_buffers
|
75
|
+
*/
|
76
|
+
VALUE
|
77
|
+
rb_mgc_get_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object))
|
78
|
+
{
|
79
|
+
return CBOOL2RVAL(rb_mgc_do_not_auto_load);
|
80
|
+
}
|
81
|
+
|
82
|
+
/*
|
83
|
+
* call-seq:
|
84
|
+
* Magic.do_not_auto_load= ( boolean ) -> boolean
|
85
|
+
*
|
86
|
+
* Sets the global +do_not_auto_load+ flag for the Magic object and each of the
|
87
|
+
* Magic object instances. This flag can be used to disable automatic loading of
|
88
|
+
* the Magic database files.
|
89
|
+
*
|
90
|
+
* Returns +true+ if the global +do_not_auto_load+ flag is set, or +false+
|
91
|
+
* otherwise.
|
92
|
+
*
|
93
|
+
* Example:
|
94
|
+
*
|
95
|
+
* Magic.do_not_auto_load #=> false
|
96
|
+
* Magic.do_not_auto_load = true #=> true
|
97
|
+
* Magic.do_not_auto_load #=> true
|
98
|
+
*
|
99
|
+
* Example:
|
100
|
+
*
|
101
|
+
* Magic.do_not_auto_load = true #=> true
|
102
|
+
* magic = Magic.new
|
103
|
+
* magic.loaded? #=> false
|
104
|
+
* magic.load_buffers(File.read(magic.paths[0] + ".mgc")) #=> nil
|
105
|
+
* magic.loaded? #=> true
|
106
|
+
*
|
107
|
+
* See also: Magic::new, Magic#loaded?, Magic#load and Magic#load_buffers
|
108
|
+
*/
|
109
|
+
VALUE
|
110
|
+
rb_mgc_set_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object), VALUE value)
|
111
|
+
{
|
112
|
+
rb_mgc_do_not_auto_load = RVAL2CBOOL(value);
|
113
|
+
return value;
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
* call-seq:
|
118
|
+
* Magic.do_not_stop_on_error -> boolean
|
119
|
+
*
|
120
|
+
* Returns +true+ if the global +do_not_stop_on_error+ flag is set, or +false+
|
121
|
+
* otherwise.
|
122
|
+
*
|
123
|
+
* Example:
|
124
|
+
*
|
125
|
+
* Magic.do_not_stop_on_error #=> false
|
126
|
+
* Magic.do_not_stop_on_error = true #=> true
|
127
|
+
* Magic.do_not_stop_on_error #=> true
|
128
|
+
*
|
129
|
+
* See also: Magic::new, Magic::open and Magic#do_not_stop_on_error
|
130
|
+
*/
|
131
|
+
VALUE
|
132
|
+
rb_mgc_get_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object))
|
133
|
+
{
|
134
|
+
return CBOOL2RVAL(rb_mgc_do_not_stop_on_error);
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* call-seq:
|
139
|
+
* Magic.do_not_stop_on_error= (boolean) -> boolean
|
140
|
+
*
|
141
|
+
* Example:
|
142
|
+
*
|
143
|
+
* Magic.do_not_stop_on_error #=> false
|
144
|
+
* Magic.do_not_stop_on_error = true #=> true
|
145
|
+
* Magic.do_not_stop_on_error #=> true
|
146
|
+
*
|
147
|
+
* See also: Magic::new, Magic::open and Magic#do_not_stop_on_error
|
148
|
+
*/
|
149
|
+
VALUE
|
150
|
+
rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
|
151
|
+
{
|
152
|
+
rb_mgc_do_not_stop_on_error = RVAL2CBOOL(value);
|
153
|
+
return value;
|
154
|
+
}
|
155
|
+
|
156
|
+
/*
|
157
|
+
* call-seq:
|
158
|
+
* Magic.new -> self
|
159
|
+
* Magic.new( string, ... ) -> self
|
160
|
+
* Magic.new( array ) -> self
|
161
|
+
*
|
162
|
+
* Opens the underlying _Magic_ database and returns a new _Magic_.
|
163
|
+
*
|
164
|
+
* Example:
|
165
|
+
*
|
166
|
+
* magic = Magic.new
|
167
|
+
* magic.class #=> Magic
|
168
|
+
*
|
169
|
+
* See also: Magic::open, Magic::mime, Magic::type, Magic::encoding, Magic::compile and Magic::check
|
170
|
+
*/
|
171
|
+
VALUE
|
172
|
+
rb_mgc_initialize(VALUE object, VALUE arguments)
|
173
|
+
{
|
174
|
+
magic_object_t *mo;
|
175
|
+
const char *klass = "Magic";
|
176
|
+
|
177
|
+
if (!NIL_P(object))
|
178
|
+
klass = rb_obj_classname(object);
|
179
|
+
|
180
|
+
if (rb_block_given_p())
|
181
|
+
MAGIC_WARNING(0, "%s::new() does not take block; use %s::open() instead",
|
182
|
+
klass, klass);
|
183
|
+
|
184
|
+
if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
|
185
|
+
rb_mgc_do_not_stop_on_error = 1;
|
186
|
+
|
187
|
+
if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
|
188
|
+
rb_mgc_do_not_auto_load = 1;
|
189
|
+
|
190
|
+
MAGIC_OBJECT(mo);
|
191
|
+
mo->stop_on_errors = 1;
|
192
|
+
if (rb_mgc_do_not_stop_on_error)
|
193
|
+
mo->stop_on_errors = 0;
|
194
|
+
|
195
|
+
mo->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject,
|
196
|
+
rb_intern("Mutex")));
|
197
|
+
|
198
|
+
magic_set_flags(object, INT2NUM(MAGIC_NONE));
|
199
|
+
magic_set_paths(object, RARRAY_EMPTY);
|
200
|
+
|
201
|
+
if (rb_mgc_do_not_auto_load) {
|
202
|
+
if (!RARRAY_EMPTY_P(arguments))
|
203
|
+
MAGIC_WARNING(1, "%s::do_not_auto_load is set; using %s#new() to load "
|
204
|
+
"Magic database from a file will have no effect",
|
205
|
+
klass, klass);
|
206
|
+
return object;
|
207
|
+
}
|
208
|
+
|
209
|
+
rb_mgc_load(object, arguments);
|
210
|
+
return object;
|
211
|
+
}
|
212
|
+
|
213
|
+
/*
|
214
|
+
* call-seq:
|
215
|
+
* magic.do_not_stop_on_error -> boolean
|
216
|
+
*
|
217
|
+
* See also: Magic::new, Magic::open and Magic::do_not_stop_on_error
|
218
|
+
*/
|
219
|
+
VALUE
|
220
|
+
rb_mgc_get_do_not_stop_on_error(VALUE object)
|
221
|
+
{
|
222
|
+
magic_object_t *mo;
|
223
|
+
|
224
|
+
MAGIC_CHECK_OPEN(object);
|
225
|
+
MAGIC_OBJECT(mo);
|
226
|
+
|
227
|
+
return CBOOL2RVAL(!mo->stop_on_errors);
|
228
|
+
}
|
229
|
+
|
230
|
+
/*
|
231
|
+
* call-seq:
|
232
|
+
* magic.do_not_stop_on_error= ( boolean ) -> boolean
|
233
|
+
*
|
234
|
+
* See also: Magic::new, Magic::open and Magic::do_not_stop_on_error
|
235
|
+
*/
|
236
|
+
VALUE
|
237
|
+
rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value)
|
238
|
+
{
|
239
|
+
magic_object_t *mo;
|
240
|
+
|
241
|
+
MAGIC_CHECK_OPEN(object);
|
242
|
+
MAGIC_OBJECT(mo);
|
243
|
+
|
244
|
+
mo->stop_on_errors = !RVAL2CBOOL(value);
|
245
|
+
return value;
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* call-seq:
|
250
|
+
* magic.open? -> true or false
|
251
|
+
*
|
252
|
+
* Returns +true+ if the underlying _Magic_ database is open,
|
253
|
+
* or +false+ otherwise.
|
254
|
+
*
|
255
|
+
* Example:
|
256
|
+
*
|
257
|
+
* magic = Magic.new
|
258
|
+
* magic.open? #=> true
|
259
|
+
* magic.close #=> nil
|
260
|
+
* magic.open? #=> false
|
261
|
+
*
|
262
|
+
* See also: Magic#close?, Magic#close and Magic#new
|
263
|
+
*/
|
264
|
+
VALUE
|
265
|
+
rb_mgc_open_p(VALUE object)
|
266
|
+
{
|
267
|
+
return MAGIC_CLOSED_P(object) ? Qfalse : Qtrue;
|
268
|
+
}
|
269
|
+
|
270
|
+
/*
|
271
|
+
* call-seq:
|
272
|
+
* magic.close -> nil
|
273
|
+
*
|
274
|
+
* Closes the underlying _Magic_ database.
|
275
|
+
*
|
276
|
+
* Example:
|
277
|
+
*
|
278
|
+
* magic = Magic.new
|
279
|
+
* magic.close #=> nil
|
280
|
+
*
|
281
|
+
* See also: Magic#closed?, Magic#open? and Magic#new
|
282
|
+
*/
|
283
|
+
VALUE
|
284
|
+
rb_mgc_close(VALUE object)
|
285
|
+
{
|
286
|
+
magic_object_t *mo;
|
287
|
+
|
288
|
+
if (MAGIC_CLOSED_P(object))
|
289
|
+
return Qnil;
|
290
|
+
|
291
|
+
MAGIC_OBJECT(mo);
|
292
|
+
if (mo) {
|
293
|
+
MAGIC_SYNCHRONIZED(magic_close_internal, mo);
|
294
|
+
if (DATA_P(object))
|
295
|
+
DATA_PTR(object) = NULL;
|
296
|
+
}
|
297
|
+
|
298
|
+
return Qnil;
|
299
|
+
}
|
300
|
+
|
301
|
+
/*
|
302
|
+
* call-seq:
|
303
|
+
* magic.closed? -> true or false
|
304
|
+
*
|
305
|
+
* Returns +true+ if the underlying _Magic_ database is closed,
|
306
|
+
* or +false+ otherwise.
|
307
|
+
*
|
308
|
+
* Example:
|
309
|
+
*
|
310
|
+
* magic = Magic.new
|
311
|
+
* magic.closed? #=> false
|
312
|
+
* magic.close #=> nil
|
313
|
+
* magic.closed? #=> true
|
314
|
+
*
|
315
|
+
* See also: Magic#close, Magic#open? and #Magic#new
|
316
|
+
*/
|
317
|
+
VALUE
|
318
|
+
rb_mgc_close_p(VALUE object)
|
319
|
+
{
|
320
|
+
magic_object_t *mo;
|
321
|
+
magic_t cookie = NULL;
|
322
|
+
|
323
|
+
MAGIC_OBJECT(mo);
|
324
|
+
if (mo)
|
325
|
+
cookie = mo->cookie;
|
326
|
+
|
327
|
+
if (DATA_P(object) && cookie)
|
328
|
+
return Qfalse;
|
329
|
+
|
330
|
+
return Qtrue;
|
331
|
+
}
|
332
|
+
|
333
|
+
/*
|
334
|
+
* call-seq:
|
335
|
+
* magic.paths -> array
|
336
|
+
*
|
337
|
+
* Example:
|
338
|
+
*
|
339
|
+
* magic = Magic.new
|
340
|
+
* magic.paths #=> ["/etc/magic", "/usr/share/misc/magic"]
|
341
|
+
*
|
342
|
+
*/
|
343
|
+
VALUE
|
344
|
+
rb_mgc_get_paths(VALUE object)
|
345
|
+
{
|
346
|
+
const char *cstring = NULL;
|
347
|
+
VALUE value = Qundef;
|
348
|
+
|
349
|
+
MAGIC_CHECK_OPEN(object);
|
350
|
+
|
351
|
+
value = rb_ivar_get(object, id_at_paths);
|
352
|
+
if (!NIL_P(value) && !RARRAY_EMPTY_P(value) && !getenv("MAGIC"))
|
353
|
+
return value;
|
354
|
+
|
355
|
+
cstring = magic_getpath_wrapper();
|
356
|
+
value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":"));
|
357
|
+
RB_GC_GUARD(value);
|
358
|
+
|
359
|
+
return value;
|
360
|
+
}
|
361
|
+
|
362
|
+
/*
|
363
|
+
* call-seq:
|
364
|
+
* magic.get_parameter( integer ) -> integer
|
365
|
+
*/
|
366
|
+
VALUE
|
367
|
+
rb_mgc_get_parameter(VALUE object, VALUE tag)
|
368
|
+
{
|
369
|
+
int local_errno;
|
370
|
+
magic_object_t *mo;
|
371
|
+
magic_arguments_t ma;
|
372
|
+
|
373
|
+
MAGIC_CHECK_INTEGER_TYPE(tag);
|
374
|
+
MAGIC_CHECK_OPEN(object);
|
375
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
376
|
+
|
377
|
+
ma.type.parameter.tag = NUM2INT(tag);
|
378
|
+
|
379
|
+
MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &ma);
|
380
|
+
local_errno = errno;
|
381
|
+
|
382
|
+
if (ma.status < 0) {
|
383
|
+
if (local_errno == EINVAL)
|
384
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
|
385
|
+
local_errno,
|
386
|
+
E_PARAM_INVALID_TYPE);
|
387
|
+
|
388
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
389
|
+
}
|
390
|
+
|
391
|
+
return SIZET2NUM(ma.type.parameter.value);
|
392
|
+
}
|
393
|
+
|
394
|
+
/*
|
395
|
+
* call-seq:
|
396
|
+
* magic.set_parameter( integer, integer ) -> nil
|
397
|
+
*/
|
398
|
+
VALUE
|
399
|
+
rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
|
400
|
+
{
|
401
|
+
int local_errno;
|
402
|
+
magic_object_t *mo;
|
403
|
+
magic_arguments_t ma;
|
404
|
+
|
405
|
+
MAGIC_CHECK_INTEGER_TYPE(tag);
|
406
|
+
MAGIC_CHECK_INTEGER_TYPE(value);
|
407
|
+
MAGIC_CHECK_OPEN(object);
|
408
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
409
|
+
|
410
|
+
ma.type.parameter.tag = NUM2INT(tag);
|
411
|
+
ma.type.parameter.value = NUM2SIZET(value);
|
412
|
+
|
413
|
+
MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &ma);
|
414
|
+
local_errno = errno;
|
415
|
+
|
416
|
+
if (ma.status < 0) {
|
417
|
+
switch (local_errno) {
|
418
|
+
case EINVAL:
|
419
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
|
420
|
+
local_errno,
|
421
|
+
E_PARAM_INVALID_TYPE);
|
422
|
+
case EOVERFLOW:
|
423
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
|
424
|
+
local_errno,
|
425
|
+
E_PARAM_INVALID_VALUE);
|
426
|
+
}
|
427
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
428
|
+
}
|
429
|
+
|
430
|
+
return Qnil;
|
431
|
+
}
|
432
|
+
|
433
|
+
/*
|
434
|
+
* call-seq:
|
435
|
+
* magic.flags -> integer
|
436
|
+
*
|
437
|
+
* Example:
|
438
|
+
*
|
439
|
+
* magic = Magic.new
|
440
|
+
* magic.flags #=> 0
|
441
|
+
* magic.flags = Magic::MIME #=> 1040
|
442
|
+
* magic.flags #=> 1040
|
443
|
+
*
|
444
|
+
* See also: Magic#flags_to_a
|
445
|
+
*/
|
446
|
+
VALUE
|
447
|
+
rb_mgc_get_flags(VALUE object)
|
448
|
+
{
|
449
|
+
int local_errno;
|
450
|
+
magic_object_t *mo;
|
451
|
+
magic_arguments_t ma;
|
452
|
+
|
453
|
+
MAGIC_CHECK_OPEN(object);
|
454
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
455
|
+
|
456
|
+
MAGIC_SYNCHRONIZED(magic_get_flags_internal, &ma);
|
457
|
+
local_errno = errno;
|
458
|
+
|
459
|
+
if (ma.flags < 0 && local_errno == ENOSYS)
|
460
|
+
return rb_ivar_get(object, id_at_flags);
|
461
|
+
|
462
|
+
return INT2NUM(ma.flags);
|
463
|
+
}
|
464
|
+
|
465
|
+
/*
|
466
|
+
* call-seq:
|
467
|
+
* magic.flags= ( integer ) -> integer
|
468
|
+
*
|
469
|
+
* Example:
|
470
|
+
*
|
471
|
+
* magic = Magic.new
|
472
|
+
* magic.flags = Magic::MIME #=> 1040
|
473
|
+
* magic.flags = Magic::MIME_TYPE #=> 16
|
474
|
+
*/
|
475
|
+
VALUE
|
476
|
+
rb_mgc_set_flags(VALUE object, VALUE value)
|
477
|
+
{
|
478
|
+
int local_errno;
|
479
|
+
magic_object_t *mo;
|
480
|
+
magic_arguments_t ma;
|
481
|
+
|
482
|
+
MAGIC_CHECK_INTEGER_TYPE(value);
|
483
|
+
MAGIC_CHECK_OPEN(object);
|
484
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
485
|
+
|
486
|
+
ma.flags = NUM2INT(value);
|
487
|
+
|
488
|
+
MAGIC_SYNCHRONIZED(magic_set_flags_internal, &ma);
|
489
|
+
local_errno = errno;
|
490
|
+
|
491
|
+
if (ma.status < 0) {
|
492
|
+
switch (local_errno) {
|
493
|
+
case EINVAL:
|
494
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError,
|
495
|
+
local_errno,
|
496
|
+
E_FLAG_INVALID_TYPE);
|
497
|
+
case ENOSYS:
|
498
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eNotImplementedError,
|
499
|
+
local_errno,
|
500
|
+
E_FLAG_NOT_IMPLEMENTED);
|
501
|
+
}
|
502
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
503
|
+
}
|
504
|
+
|
505
|
+
return rb_ivar_set(object, id_at_flags, INT2NUM(ma.flags));
|
506
|
+
}
|
507
|
+
|
508
|
+
/*
|
509
|
+
* call-seq:
|
510
|
+
* magic.load -> nil
|
511
|
+
* magic.load( string, ... ) -> nil
|
512
|
+
* magic.load( array ) -> nil
|
513
|
+
*
|
514
|
+
* Example:
|
515
|
+
*
|
516
|
+
* See also: Magic#check, Magic#compile, Magic::check and Magic::compile
|
517
|
+
*/
|
518
|
+
VALUE
|
519
|
+
rb_mgc_load(VALUE object, VALUE arguments)
|
520
|
+
{
|
521
|
+
magic_object_t *mo;
|
522
|
+
magic_arguments_t ma;
|
523
|
+
const char *klass = "Magic";
|
524
|
+
VALUE value = Qundef;
|
525
|
+
|
526
|
+
if (ARRAY_P(RARRAY_FIRST(arguments)))
|
527
|
+
arguments = magic_flatten(arguments);
|
528
|
+
|
529
|
+
MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
|
530
|
+
MAGIC_CHECK_OPEN(object);
|
531
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
532
|
+
|
533
|
+
if (rb_mgc_do_not_auto_load) {
|
534
|
+
if (!NIL_P(object))
|
535
|
+
klass = rb_obj_classname(object);
|
536
|
+
|
537
|
+
MAGIC_WARNING(2, "%s::do_not_auto_load is set; using %s#load "
|
538
|
+
"will load Magic database from a file",
|
539
|
+
klass, klass);
|
540
|
+
}
|
541
|
+
|
542
|
+
ma.flags = magic_flags(object);
|
543
|
+
|
544
|
+
if (!RARRAY_EMPTY_P(arguments)) {
|
545
|
+
value = magic_join(arguments, CSTR2RVAL(":"));
|
546
|
+
ma.type.file.path = RVAL2CSTR(value);
|
547
|
+
}
|
548
|
+
else
|
549
|
+
ma.type.file.path = magic_getpath_wrapper();
|
550
|
+
|
551
|
+
magic_set_paths(object, RARRAY_EMPTY);
|
552
|
+
|
553
|
+
MAGIC_SYNCHRONIZED(magic_load_internal, &ma);
|
554
|
+
if (ma.status < 0) {
|
555
|
+
mo->database_loaded = 0;
|
556
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
557
|
+
}
|
558
|
+
mo->database_loaded = 1;
|
559
|
+
|
560
|
+
value = magic_split(CSTR2RVAL(ma.type.file.path), CSTR2RVAL(":"));
|
561
|
+
magic_set_paths(object, value);
|
562
|
+
RB_GC_GUARD(value);
|
563
|
+
|
564
|
+
return Qnil;
|
565
|
+
}
|
566
|
+
|
567
|
+
/*
|
568
|
+
* call-seq:
|
569
|
+
* magic.load_buffers( string, ... ) -> nil
|
570
|
+
* magic.load_buffers( array ) -> nil
|
571
|
+
*
|
572
|
+
* See also: Magic#load and Magic::do_not_auto_load
|
573
|
+
*/
|
574
|
+
VALUE
|
575
|
+
rb_mgc_load_buffers(VALUE object, VALUE arguments)
|
576
|
+
{
|
577
|
+
size_t count;
|
578
|
+
int local_errno;
|
579
|
+
magic_object_t *mo;
|
580
|
+
magic_arguments_t ma;
|
581
|
+
void **pointers = NULL;
|
582
|
+
size_t *sizes = NULL;
|
583
|
+
VALUE value = Qundef;
|
584
|
+
|
585
|
+
count = (size_t)RARRAY_LEN(arguments);
|
586
|
+
MAGIC_CHECK_ARGUMENT_MISSING(count, 1);
|
587
|
+
|
588
|
+
if (ARRAY_P(RARRAY_FIRST(arguments))) {
|
589
|
+
arguments = magic_flatten(arguments);
|
590
|
+
count = (size_t)RARRAY_LEN(arguments);
|
591
|
+
}
|
592
|
+
|
593
|
+
MAGIC_CHECK_ARRAY_EMPTY(arguments);
|
594
|
+
MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
|
595
|
+
MAGIC_CHECK_OPEN(object);
|
596
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
597
|
+
|
598
|
+
pointers = ALLOC_N(void *, count);
|
599
|
+
if (!pointers) {
|
600
|
+
local_errno = ENOMEM;
|
601
|
+
goto error;
|
602
|
+
}
|
603
|
+
|
604
|
+
sizes = ALLOC_N(size_t, count);
|
605
|
+
if (!sizes) {
|
606
|
+
ruby_xfree(pointers);
|
607
|
+
local_errno = ENOMEM;
|
608
|
+
goto error;
|
609
|
+
}
|
610
|
+
|
611
|
+
for (size_t i = 0; i < count; i++) {
|
612
|
+
value = RARRAY_AREF(arguments, (long)i);
|
613
|
+
pointers[i] = (void *)RSTRING_PTR(value);
|
614
|
+
sizes[i] = (size_t)RSTRING_LEN(value);
|
615
|
+
}
|
616
|
+
|
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
|
+
magic_set_paths(object, RARRAY_EMPTY);
|
623
|
+
|
624
|
+
MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &ma);
|
625
|
+
if (ma.status < 0) {
|
626
|
+
local_errno = errno;
|
627
|
+
ruby_xfree(pointers);
|
628
|
+
ruby_xfree(sizes);
|
629
|
+
goto error;
|
630
|
+
}
|
631
|
+
mo->database_loaded = 1;
|
632
|
+
|
633
|
+
ruby_xfree(pointers);
|
634
|
+
ruby_xfree(sizes);
|
635
|
+
|
636
|
+
return Qnil;
|
637
|
+
error:
|
638
|
+
mo->database_loaded = 0;
|
639
|
+
|
640
|
+
if (local_errno == ENOMEM)
|
641
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
642
|
+
local_errno,
|
643
|
+
E_NOT_ENOUGH_MEMORY);
|
644
|
+
|
645
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
646
|
+
}
|
647
|
+
|
648
|
+
/*
|
649
|
+
* call-seq:
|
650
|
+
* magic.loaded? -> true or false
|
651
|
+
*
|
652
|
+
* Returns +true+ if at least a single Magic database file had been loaded, or
|
653
|
+
* +false+ otherwise. Magic database files can be loaded from a file or from an
|
654
|
+
* in-memory buffer.
|
655
|
+
*
|
656
|
+
* Example:
|
657
|
+
*
|
658
|
+
* magic = Magic.new
|
659
|
+
* magic.loaded? #=> true
|
660
|
+
*
|
661
|
+
* Example:
|
662
|
+
*
|
663
|
+
* Magic.do_not_auto_load = true #=> true
|
664
|
+
* magic = Magic.new
|
665
|
+
* magic.loaded? #=> false
|
666
|
+
*
|
667
|
+
* See also: Magic#load and Magic#load_buffers
|
668
|
+
*/
|
669
|
+
VALUE
|
670
|
+
rb_mgc_load_p(VALUE object)
|
671
|
+
{
|
672
|
+
magic_object_t *mo;
|
673
|
+
|
674
|
+
MAGIC_CHECK_OPEN(object);
|
675
|
+
MAGIC_OBJECT(mo);
|
676
|
+
|
677
|
+
return CBOOL2RVAL(mo->database_loaded);
|
678
|
+
}
|
679
|
+
|
680
|
+
/*
|
681
|
+
* call-seq:
|
682
|
+
* magic.compile( string ) -> nil
|
683
|
+
* magic.compile( array ) -> nil
|
684
|
+
*
|
685
|
+
* See also: Magic#check, Magic::check and Magic::compile
|
686
|
+
*/
|
687
|
+
VALUE
|
688
|
+
rb_mgc_compile(VALUE object, VALUE value)
|
689
|
+
{
|
690
|
+
magic_object_t *mo;
|
691
|
+
magic_arguments_t ma;
|
692
|
+
|
693
|
+
MAGIC_CHECK_STRING_TYPE(value);
|
694
|
+
MAGIC_CHECK_OPEN(object);
|
695
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
696
|
+
|
697
|
+
ma.flags = magic_flags(object);
|
698
|
+
ma.type.file.path = RVAL2CSTR(value);
|
699
|
+
|
700
|
+
MAGIC_SYNCHRONIZED(magic_compile_internal, &ma);
|
701
|
+
if (ma.status < 0)
|
702
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
703
|
+
|
704
|
+
return Qnil;
|
705
|
+
}
|
706
|
+
|
707
|
+
/*
|
708
|
+
* call-seq:
|
709
|
+
* magic.check( string ) -> true or false
|
710
|
+
* magic.check( array ) -> true or false
|
711
|
+
*
|
712
|
+
* See also: Magic#compile, Magic::compile and Magic::check
|
713
|
+
*/
|
714
|
+
VALUE
|
715
|
+
rb_mgc_check(VALUE object, VALUE value)
|
716
|
+
{
|
717
|
+
magic_object_t *mo;
|
718
|
+
magic_arguments_t ma;
|
719
|
+
|
720
|
+
MAGIC_CHECK_STRING_TYPE(value);
|
721
|
+
MAGIC_CHECK_OPEN(object);
|
722
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
723
|
+
|
724
|
+
ma.flags = magic_flags(object);
|
725
|
+
ma.type.file.path = RVAL2CSTR(value);
|
726
|
+
|
727
|
+
MAGIC_SYNCHRONIZED(magic_check_internal, &ma);
|
728
|
+
return ma.status < 0 ? Qfalse : Qtrue;
|
729
|
+
}
|
730
|
+
|
731
|
+
/*
|
732
|
+
* call-seq:
|
733
|
+
* magic.file( object ) -> string or array
|
734
|
+
* magic.file( string ) -> string or array
|
735
|
+
*
|
736
|
+
* See also: Magic#buffer and Magic#descriptor
|
737
|
+
*/
|
738
|
+
VALUE
|
739
|
+
rb_mgc_file(VALUE object, VALUE value)
|
740
|
+
{
|
741
|
+
magic_object_t *mo;
|
742
|
+
magic_arguments_t ma;
|
743
|
+
const char *empty = "(null)";
|
744
|
+
|
745
|
+
if (NIL_P(value))
|
746
|
+
goto error;
|
747
|
+
|
748
|
+
MAGIC_CHECK_OPEN(object);
|
749
|
+
MAGIC_CHECK_LOADED(object);
|
750
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
751
|
+
|
752
|
+
if (rb_respond_to(value, rb_intern("to_io")))
|
753
|
+
return rb_mgc_descriptor(object, value);
|
754
|
+
|
755
|
+
value = magic_path(value);
|
756
|
+
if (NIL_P(value))
|
757
|
+
goto error;
|
758
|
+
|
759
|
+
ma.stop_on_errors = mo->stop_on_errors;
|
760
|
+
ma.flags = magic_flags(object);
|
761
|
+
ma.type.file.path = RVAL2CSTR(value);
|
762
|
+
|
763
|
+
MAGIC_SYNCHRONIZED(magic_file_internal, &ma);
|
764
|
+
if (!ma.result) {
|
765
|
+
/*
|
766
|
+
* Handle the case when the "ERROR" flag is set regardless of the
|
767
|
+
* current version of the underlying Magic library.
|
768
|
+
*
|
769
|
+
* Prior to version 5.15 the correct behavior that concerns the
|
770
|
+
* following IEEE 1003.1 standards was broken:
|
771
|
+
*
|
772
|
+
* http://pubs.opengroup.org/onlinepubs/007904975/utilities/file.html
|
773
|
+
* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html
|
774
|
+
*
|
775
|
+
* This is an attempt to mitigate the problem and correct it to achieve
|
776
|
+
* the desired behavior as per the standards.
|
777
|
+
*/
|
778
|
+
if (mo->stop_on_errors || (ma.flags & MAGIC_ERROR))
|
779
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
780
|
+
else
|
781
|
+
ma.result = magic_error_wrapper(ma.cookie);
|
782
|
+
}
|
783
|
+
if (!ma.result)
|
784
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN);
|
785
|
+
|
786
|
+
assert(ma.result != NULL && \
|
787
|
+
"Must be a valid pointer to `const char' type");
|
788
|
+
|
789
|
+
/*
|
790
|
+
* Depending on the version of the underlying Magic library the magic_file()
|
791
|
+
* function can fail and either yield no results or return the "(null)"
|
792
|
+
* string instead. Often this would indicate that an older version of the
|
793
|
+
* Magic library is in use.
|
794
|
+
*/
|
795
|
+
assert(strncmp(ma.result, empty, strlen(empty)) != 0 && \
|
796
|
+
"Empty or invalid result");
|
797
|
+
|
798
|
+
return magic_return(&ma);
|
799
|
+
error:
|
800
|
+
MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object");
|
801
|
+
}
|
802
|
+
|
803
|
+
/*
|
804
|
+
* call-seq:
|
805
|
+
* magic.buffer( string ) -> string or array
|
806
|
+
*
|
807
|
+
* See also: Magic#file and Magic#descriptor
|
808
|
+
*/
|
809
|
+
VALUE
|
810
|
+
rb_mgc_buffer(VALUE object, VALUE value)
|
811
|
+
{
|
812
|
+
magic_object_t *mo;
|
813
|
+
magic_arguments_t ma;
|
814
|
+
|
815
|
+
MAGIC_CHECK_STRING_TYPE(value);
|
816
|
+
MAGIC_CHECK_OPEN(object);
|
817
|
+
MAGIC_CHECK_LOADED(object);
|
818
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
819
|
+
|
820
|
+
StringValue(value);
|
821
|
+
|
822
|
+
ma.flags = magic_flags(object);
|
823
|
+
ma.type.buffers.pointers = (void **)RSTRING_PTR(value);
|
824
|
+
ma.type.buffers.sizes = (size_t *)RSTRING_LEN(value);
|
825
|
+
|
826
|
+
MAGIC_SYNCHRONIZED(magic_buffer_internal, &ma);
|
827
|
+
if (!ma.result)
|
828
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
829
|
+
|
830
|
+
assert(ma.result != NULL && \
|
831
|
+
"Must be a valid pointer to `const char' type");
|
832
|
+
|
833
|
+
return magic_return(&ma);
|
834
|
+
}
|
835
|
+
|
836
|
+
/*
|
837
|
+
* call-seq:
|
838
|
+
* magic.descriptor( object ) -> string or array
|
839
|
+
* magic.descriptor( integer ) -> string or array
|
840
|
+
*
|
841
|
+
* See also: Magic#file and Magic#buffer
|
842
|
+
*/
|
843
|
+
VALUE
|
844
|
+
rb_mgc_descriptor(VALUE object, VALUE value)
|
845
|
+
{
|
846
|
+
int local_errno;
|
847
|
+
magic_object_t *mo;
|
848
|
+
magic_arguments_t ma;
|
849
|
+
|
850
|
+
if (rb_respond_to(value, rb_intern("to_io")))
|
851
|
+
value = INT2NUM(magic_fileno(value));
|
852
|
+
|
853
|
+
MAGIC_CHECK_INTEGER_TYPE(value);
|
854
|
+
MAGIC_CHECK_OPEN(object);
|
855
|
+
MAGIC_CHECK_LOADED(object);
|
856
|
+
MAGIC_COOKIE(mo, ma.cookie);
|
857
|
+
|
858
|
+
ma.flags = magic_flags(object);
|
859
|
+
ma.type.file.fd = NUM2INT(value);
|
860
|
+
|
861
|
+
MAGIC_SYNCHRONIZED(magic_descriptor_internal, &ma);
|
862
|
+
local_errno = errno;
|
863
|
+
|
864
|
+
if (!ma.result) {
|
865
|
+
if (local_errno == EBADF)
|
866
|
+
rb_raise(rb_eIOError, "Bad file descriptor");
|
867
|
+
|
868
|
+
MAGIC_LIBRARY_ERROR(ma.cookie);
|
869
|
+
}
|
870
|
+
|
871
|
+
assert(ma.result != NULL && \
|
872
|
+
"Must be a valid pointer to `const char' type");
|
873
|
+
|
874
|
+
return magic_return(&ma);
|
875
|
+
}
|
876
|
+
|
877
|
+
/*
|
878
|
+
* call-seq:
|
879
|
+
* Magic.version -> integer
|
880
|
+
*
|
881
|
+
* Example:
|
882
|
+
*
|
883
|
+
* Magic.version #=> 517
|
884
|
+
*
|
885
|
+
* See also: Magic::version_to_a and Magic::version_to_s
|
886
|
+
*/
|
887
|
+
VALUE
|
888
|
+
rb_mgc_version(RB_UNUSED_VAR(VALUE object))
|
889
|
+
{
|
890
|
+
return INT2NUM(magic_version_wrapper());
|
891
|
+
}
|
892
|
+
|
893
|
+
static inline void*
|
894
|
+
nogvl_magic_load(void *data)
|
895
|
+
{
|
896
|
+
magic_arguments_t *ma = data;
|
897
|
+
|
898
|
+
ma->status = magic_load_wrapper(ma->cookie,
|
899
|
+
ma->type.file.path,
|
900
|
+
ma->flags);
|
901
|
+
return NULL;
|
902
|
+
}
|
903
|
+
|
904
|
+
static inline void*
|
905
|
+
nogvl_magic_compile(void *data)
|
906
|
+
{
|
907
|
+
magic_arguments_t *ma = data;
|
908
|
+
|
909
|
+
ma->status = magic_compile_wrapper(ma->cookie,
|
910
|
+
ma->type.file.path,
|
911
|
+
ma->flags);
|
912
|
+
return NULL;
|
913
|
+
}
|
914
|
+
|
915
|
+
static inline void*
|
916
|
+
nogvl_magic_check(void *data)
|
917
|
+
{
|
918
|
+
magic_arguments_t *ma = data;
|
919
|
+
|
920
|
+
ma->status = magic_check_wrapper(ma->cookie,
|
921
|
+
ma->type.file.path,
|
922
|
+
ma->flags);
|
923
|
+
return NULL;
|
924
|
+
}
|
925
|
+
|
926
|
+
static inline void*
|
927
|
+
nogvl_magic_file(void *data)
|
928
|
+
{
|
929
|
+
magic_arguments_t *ma = data;
|
930
|
+
|
931
|
+
ma->result = magic_file_wrapper(ma->cookie,
|
932
|
+
ma->type.file.path,
|
933
|
+
ma->flags);
|
934
|
+
return NULL;
|
935
|
+
}
|
936
|
+
|
937
|
+
static inline void*
|
938
|
+
nogvl_magic_descriptor(void *data)
|
939
|
+
{
|
940
|
+
magic_arguments_t *ma = data;
|
941
|
+
|
942
|
+
ma->result = magic_descriptor_wrapper(ma->cookie,
|
943
|
+
ma->type.file.fd,
|
944
|
+
ma->flags);
|
945
|
+
return NULL;
|
946
|
+
}
|
947
|
+
|
948
|
+
static inline VALUE
|
949
|
+
magic_get_parameter_internal(void *data)
|
950
|
+
{
|
951
|
+
size_t value;
|
952
|
+
magic_arguments_t *ma = data;
|
953
|
+
|
954
|
+
ma->status = magic_getparam_wrapper(ma->cookie,
|
955
|
+
ma->type.parameter.tag,
|
956
|
+
&value);
|
957
|
+
ma->type.parameter.value = value;
|
958
|
+
return (VALUE)NULL;
|
959
|
+
}
|
960
|
+
|
961
|
+
static inline VALUE
|
962
|
+
magic_set_parameter_internal(void *data)
|
963
|
+
{
|
964
|
+
size_t value;
|
965
|
+
magic_arguments_t *ma = data;
|
966
|
+
|
967
|
+
value = ma->type.parameter.value;
|
968
|
+
ma->status = magic_setparam_wrapper(ma->cookie,
|
969
|
+
ma->type.parameter.tag,
|
970
|
+
&value);
|
971
|
+
return (VALUE)NULL;
|
972
|
+
}
|
973
|
+
|
974
|
+
static inline VALUE
|
975
|
+
magic_get_flags_internal(void *data)
|
976
|
+
{
|
977
|
+
magic_arguments_t *ma = data;
|
978
|
+
|
979
|
+
ma->flags = magic_getflags_wrapper(ma->cookie);
|
980
|
+
return (VALUE)NULL;
|
981
|
+
}
|
982
|
+
|
983
|
+
static inline VALUE
|
984
|
+
magic_set_flags_internal(void *data)
|
985
|
+
{
|
986
|
+
magic_arguments_t *ma = data;
|
987
|
+
|
988
|
+
ma->status = magic_setflags_wrapper(ma->cookie, ma->flags);
|
989
|
+
return (VALUE)NULL;
|
990
|
+
}
|
991
|
+
|
992
|
+
static inline VALUE
|
993
|
+
magic_close_internal(void *data)
|
994
|
+
{
|
995
|
+
magic_library_close(data);
|
996
|
+
return Qnil;
|
997
|
+
}
|
998
|
+
|
999
|
+
static inline VALUE
|
1000
|
+
magic_load_internal(void *data)
|
1001
|
+
{
|
1002
|
+
return (VALUE)NOGVL(nogvl_magic_load, data);
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
static inline VALUE
|
1006
|
+
magic_load_buffers_internal(void *data)
|
1007
|
+
{
|
1008
|
+
magic_arguments_t *ma = data;
|
1009
|
+
|
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
|
+
return (VALUE)NULL;
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
static inline VALUE
|
1019
|
+
magic_compile_internal(void *data)
|
1020
|
+
{
|
1021
|
+
return (VALUE)NOGVL(nogvl_magic_compile, data);
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
static inline VALUE
|
1025
|
+
magic_check_internal(void *data)
|
1026
|
+
{
|
1027
|
+
return (VALUE)NOGVL(nogvl_magic_check, data);
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
static VALUE
|
1031
|
+
magic_file_internal(void *data)
|
1032
|
+
{
|
1033
|
+
int local_errno;
|
1034
|
+
int old_flags = 0;
|
1035
|
+
int restore_flags = 0;
|
1036
|
+
magic_arguments_t *ma = data;
|
1037
|
+
|
1038
|
+
if (ma->stop_on_errors) {
|
1039
|
+
old_flags = ma->flags;
|
1040
|
+
ma->flags |= MAGIC_ERROR;
|
1041
|
+
restore_flags = 1;
|
1042
|
+
}
|
1043
|
+
if (ma->flags & MAGIC_CONTINUE) {
|
1044
|
+
old_flags = ma->flags;
|
1045
|
+
ma->flags |= MAGIC_RAW;
|
1046
|
+
restore_flags = 1;
|
1047
|
+
}
|
1048
|
+
if (restore_flags && ma->flags)
|
1049
|
+
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1050
|
+
|
1051
|
+
NOGVL(nogvl_magic_file, ma);
|
1052
|
+
local_errno = errno;
|
1053
|
+
/*
|
1054
|
+
* The Magic library often does not correctly report errors,
|
1055
|
+
* especially when certain flags (such as e.g., MAGIC_EXTENSION,
|
1056
|
+
* etc.) are set. Attempt to obtain an error code first from the
|
1057
|
+
* Magic library itself, and if that does not work, then from
|
1058
|
+
* the saved errno value.
|
1059
|
+
*/
|
1060
|
+
if (magic_errno_wrapper(ma->cookie))
|
1061
|
+
ma->status = -1;
|
1062
|
+
else if (local_errno)
|
1063
|
+
ma->status = -1;
|
1064
|
+
|
1065
|
+
if (restore_flags && old_flags)
|
1066
|
+
magic_setflags_wrapper(ma->cookie, old_flags);
|
1067
|
+
|
1068
|
+
return (VALUE)NULL;
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
static VALUE
|
1072
|
+
magic_buffer_internal(void *data)
|
1073
|
+
{
|
1074
|
+
int old_flags = 0;
|
1075
|
+
int restore_flags = 0;
|
1076
|
+
magic_arguments_t *ma = data;
|
1077
|
+
|
1078
|
+
if (ma->flags & MAGIC_CONTINUE) {
|
1079
|
+
old_flags = ma->flags;
|
1080
|
+
ma->flags |= MAGIC_RAW;
|
1081
|
+
restore_flags = 1;
|
1082
|
+
}
|
1083
|
+
if (restore_flags && ma->flags)
|
1084
|
+
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1085
|
+
|
1086
|
+
ma->result = magic_buffer_wrapper(ma->cookie,
|
1087
|
+
(const void *)ma->type.buffers.pointers,
|
1088
|
+
(size_t)ma->type.buffers.sizes,
|
1089
|
+
ma->flags);
|
1090
|
+
if (restore_flags && old_flags)
|
1091
|
+
magic_setflags_wrapper(ma->cookie, old_flags);
|
1092
|
+
|
1093
|
+
return (VALUE)NULL;
|
1094
|
+
}
|
1095
|
+
|
1096
|
+
static VALUE
|
1097
|
+
magic_descriptor_internal(void *data)
|
1098
|
+
{
|
1099
|
+
int old_flags = 0;
|
1100
|
+
int restore_flags = 0;
|
1101
|
+
magic_arguments_t *ma = data;
|
1102
|
+
|
1103
|
+
if (ma->flags & MAGIC_CONTINUE) {
|
1104
|
+
old_flags = ma->flags;
|
1105
|
+
ma->flags |= MAGIC_RAW;
|
1106
|
+
restore_flags = 1;
|
1107
|
+
}
|
1108
|
+
if (restore_flags && ma->flags)
|
1109
|
+
magic_setflags_wrapper(ma->cookie, ma->flags);
|
1110
|
+
|
1111
|
+
NOGVL(nogvl_magic_descriptor, ma);
|
1112
|
+
|
1113
|
+
if (restore_flags && old_flags)
|
1114
|
+
magic_setflags_wrapper(ma->cookie, old_flags);
|
1115
|
+
|
1116
|
+
return (VALUE)NULL;
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
static VALUE
|
1120
|
+
magic_allocate(VALUE klass)
|
1121
|
+
{
|
1122
|
+
int local_errno;
|
1123
|
+
magic_object_t *mo;
|
1124
|
+
|
1125
|
+
mo = (magic_object_t *)ruby_xmalloc(sizeof(magic_object_t));
|
1126
|
+
local_errno = ENOMEM;
|
1127
|
+
|
1128
|
+
if (!mo) {
|
1129
|
+
errno = local_errno;
|
1130
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1131
|
+
local_errno,
|
1132
|
+
E_NOT_ENOUGH_MEMORY);
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
mo->cookie = NULL;
|
1136
|
+
mo->mutex = Qundef;
|
1137
|
+
mo->database_loaded = 0;
|
1138
|
+
mo->stop_on_errors = 0;
|
1139
|
+
|
1140
|
+
mo->cookie = magic_open_wrapper(MAGIC_NONE);
|
1141
|
+
local_errno = ENOMEM;
|
1142
|
+
|
1143
|
+
if (!mo->cookie) {
|
1144
|
+
ruby_xfree(mo);
|
1145
|
+
mo = NULL;
|
1146
|
+
errno = local_errno;
|
1147
|
+
MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
|
1148
|
+
local_errno,
|
1149
|
+
E_MAGIC_LIBRARY_INITIALIZE);
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
return Data_Wrap_Struct(klass, magic_mark, magic_free, mo);
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
static inline void
|
1156
|
+
magic_library_close(void *data)
|
1157
|
+
{
|
1158
|
+
magic_object_t *mo = data;
|
1159
|
+
|
1160
|
+
assert(mo != NULL && \
|
1161
|
+
"Must be a valid pointer to `magic_object_t' type");
|
1162
|
+
|
1163
|
+
if (mo->cookie)
|
1164
|
+
magic_close_wrapper(mo->cookie);
|
1165
|
+
|
1166
|
+
mo->cookie = NULL;
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
static inline void
|
1170
|
+
magic_mark(void *data)
|
1171
|
+
{
|
1172
|
+
magic_object_t *mo = data;
|
1173
|
+
|
1174
|
+
assert(mo != NULL && \
|
1175
|
+
"Must be a valid pointer to `magic_object_t' type");
|
1176
|
+
|
1177
|
+
rb_gc_mark(mo->mutex);
|
1178
|
+
}
|
1179
|
+
|
1180
|
+
static inline void
|
1181
|
+
magic_free(void *data)
|
1182
|
+
{
|
1183
|
+
magic_object_t *mo = data;
|
1184
|
+
|
1185
|
+
assert(mo != NULL && \
|
1186
|
+
"Must be a valid pointer to `magic_object_t' type");
|
1187
|
+
|
1188
|
+
if (mo->cookie)
|
1189
|
+
magic_library_close(data);
|
1190
|
+
|
1191
|
+
mo->cookie = NULL;
|
1192
|
+
mo->mutex = Qundef;
|
1193
|
+
|
1194
|
+
ruby_xfree(mo);
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
static inline VALUE
|
1198
|
+
magic_exception_wrapper(VALUE value)
|
1199
|
+
{
|
1200
|
+
magic_exception_t *e = (struct magic_exception *)value;
|
1201
|
+
|
1202
|
+
return rb_exc_new2(e->klass, e->magic_error);
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
static VALUE
|
1206
|
+
magic_exception(void *data)
|
1207
|
+
{
|
1208
|
+
magic_exception_t *e = data;
|
1209
|
+
int exception = 0;
|
1210
|
+
VALUE object = Qundef;
|
1211
|
+
|
1212
|
+
assert(e != NULL && \
|
1213
|
+
"Must be a valid pointer to `magic_exception_t' type");
|
1214
|
+
|
1215
|
+
object = rb_protect(magic_exception_wrapper, (VALUE)e, &exception);
|
1216
|
+
|
1217
|
+
if (exception)
|
1218
|
+
rb_jump_tag(exception);
|
1219
|
+
|
1220
|
+
rb_iv_set(object, "@errno", INT2NUM(e->magic_errno));
|
1221
|
+
RB_GC_GUARD(object);
|
1222
|
+
|
1223
|
+
return object;
|
1224
|
+
}
|
1225
|
+
|
1226
|
+
static inline VALUE
|
1227
|
+
magic_generic_error(VALUE klass, int magic_errno, const char *magic_error)
|
1228
|
+
{
|
1229
|
+
magic_exception_t e;
|
1230
|
+
|
1231
|
+
e.magic_errno = magic_errno;
|
1232
|
+
e.magic_error = magic_error;
|
1233
|
+
e.klass = klass;
|
1234
|
+
|
1235
|
+
return magic_exception(&e);
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
static VALUE
|
1239
|
+
magic_library_error(VALUE klass, void *data)
|
1240
|
+
{
|
1241
|
+
magic_exception_t e;
|
1242
|
+
const char *message = NULL;
|
1243
|
+
const char *empty = "(null)";
|
1244
|
+
magic_t cookie = data;
|
1245
|
+
|
1246
|
+
assert(cookie != NULL && \
|
1247
|
+
"Must be a valid pointer to `magic_t' type");
|
1248
|
+
|
1249
|
+
e.magic_errno = -1;
|
1250
|
+
e.magic_error = error(E_UNKNOWN);
|
1251
|
+
e.klass = klass;
|
1252
|
+
|
1253
|
+
message = magic_error_wrapper(cookie);
|
1254
|
+
if (message) {
|
1255
|
+
e.magic_errno = magic_errno_wrapper(cookie);
|
1256
|
+
e.magic_error = message;
|
1257
|
+
}
|
1258
|
+
|
1259
|
+
assert(strncmp(e.magic_error, empty, strlen(empty)) != 0 && \
|
1260
|
+
"Empty or invalid error message");
|
1261
|
+
|
1262
|
+
return magic_exception(&e);
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
VALUE
|
1266
|
+
magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
|
1267
|
+
{
|
1268
|
+
magic_object_t *mo;
|
1269
|
+
|
1270
|
+
MAGIC_OBJECT(mo);
|
1271
|
+
rb_funcall(mo->mutex, rb_intern("lock"), 0, Qundef);
|
1272
|
+
|
1273
|
+
return rb_ensure(function, (VALUE)data, magic_unlock, object);
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
VALUE
|
1277
|
+
magic_unlock(VALUE object)
|
1278
|
+
{
|
1279
|
+
magic_object_t *mo;
|
1280
|
+
|
1281
|
+
MAGIC_OBJECT(mo);
|
1282
|
+
rb_funcall(mo->mutex, rb_intern("unlock"), 0, Qundef);
|
1283
|
+
|
1284
|
+
return Qnil;
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
static VALUE
|
1288
|
+
magic_return(void *data)
|
1289
|
+
{
|
1290
|
+
magic_arguments_t *ma = data;
|
1291
|
+
const char *unknown = "???";
|
1292
|
+
VALUE separator = Qundef;
|
1293
|
+
VALUE array = Qundef;
|
1294
|
+
VALUE string = Qundef;
|
1295
|
+
|
1296
|
+
string = CSTR2RVAL(ma->result);
|
1297
|
+
RB_GC_GUARD(string);
|
1298
|
+
|
1299
|
+
/*
|
1300
|
+
* The value below is a field separator that can be used to split results
|
1301
|
+
* when the CONTINUE flag is set causing all valid matches found by the
|
1302
|
+
* Magic library to be returned.
|
1303
|
+
*/
|
1304
|
+
if (ma->flags & MAGIC_CONTINUE)
|
1305
|
+
separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR);
|
1306
|
+
|
1307
|
+
if (ma->flags & MAGIC_EXTENSION) {
|
1308
|
+
/*
|
1309
|
+
* A possible I/O-related error has occurred, and there is very
|
1310
|
+
* little sense processing the results, so return string as-is.
|
1311
|
+
*/
|
1312
|
+
if (ma->status < 0)
|
1313
|
+
return string;
|
1314
|
+
/*
|
1315
|
+
* A number of Magic flags that support primarily files e.g.,
|
1316
|
+
* MAGIC_EXTENSION, etc., would not return a meaningful value for
|
1317
|
+
* directories and special files, and such. Thus, it's better to
|
1318
|
+
* return an empty string, to indicate lack of results, rather
|
1319
|
+
* than a confusing string consisting of three questions marks.
|
1320
|
+
*/
|
1321
|
+
if (strncmp(ma->result, unknown, strlen(unknown)) == 0)
|
1322
|
+
return CSTR2RVAL("");
|
1323
|
+
|
1324
|
+
separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR);
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
if (ma->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
|
1328
|
+
array = magic_split(string, separator);
|
1329
|
+
RB_GC_GUARD(array);
|
1330
|
+
return (RARRAY_LEN(array) > 1) ? array : magic_shift(array);
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
return string;
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
static inline int
|
1337
|
+
magic_flags(VALUE object)
|
1338
|
+
{
|
1339
|
+
return NUM2INT(rb_ivar_get(object, id_at_flags));
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
static inline int
|
1343
|
+
magic_set_flags(VALUE object, VALUE value)
|
1344
|
+
{
|
1345
|
+
return NUM2INT(rb_ivar_set(object, id_at_flags, value));
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
static inline VALUE
|
1349
|
+
magic_set_paths(VALUE object, VALUE value)
|
1350
|
+
{
|
1351
|
+
return rb_ivar_set(object, id_at_paths, value);
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
void
|
1355
|
+
Init_magic(void)
|
1356
|
+
{
|
1357
|
+
id_at_paths = rb_intern("@paths");
|
1358
|
+
id_at_flags = rb_intern("@flags");
|
1359
|
+
|
1360
|
+
rb_cMagic = rb_define_class("Magic", rb_cObject);
|
1361
|
+
rb_define_alloc_func(rb_cMagic, magic_allocate);
|
1362
|
+
/*
|
1363
|
+
* Raised when _Magic_ encounters an error.
|
1364
|
+
*/
|
1365
|
+
rb_mgc_eError = rb_define_class_under(rb_cMagic, "Error", rb_eStandardError);
|
1366
|
+
/*
|
1367
|
+
* Stores current value of +errno+
|
1368
|
+
*/
|
1369
|
+
rb_define_attr(rb_mgc_eError, "errno", 1, 0);
|
1370
|
+
/*
|
1371
|
+
* Raised when
|
1372
|
+
*/
|
1373
|
+
rb_mgc_eMagicError = rb_define_class_under(rb_cMagic, "MagicError", rb_mgc_eError);
|
1374
|
+
/*
|
1375
|
+
* Raised when
|
1376
|
+
*/
|
1377
|
+
rb_mgc_eLibraryError = rb_define_class_under(rb_cMagic, "LibraryError", rb_mgc_eError);
|
1378
|
+
/*
|
1379
|
+
* Raised when
|
1380
|
+
*/
|
1381
|
+
rb_mgc_eParameterError = rb_define_class_under(rb_cMagic, "ParameterError", rb_mgc_eError);
|
1382
|
+
/*
|
1383
|
+
* Raised when
|
1384
|
+
*/
|
1385
|
+
rb_mgc_eFlagsError = rb_define_class_under(rb_cMagic, "FlagsError", rb_mgc_eError);
|
1386
|
+
/*
|
1387
|
+
* Raised when
|
1388
|
+
*/
|
1389
|
+
rb_mgc_eNotImplementedError = rb_define_class_under(rb_cMagic, "NotImplementedError", rb_mgc_eError);
|
1390
|
+
|
1391
|
+
rb_define_singleton_method(rb_cMagic, "do_not_auto_load", RUBY_METHOD_FUNC(rb_mgc_get_do_not_auto_load_global), 0);
|
1392
|
+
rb_define_singleton_method(rb_cMagic, "do_not_auto_load=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_auto_load_global), 1);
|
1393
|
+
|
1394
|
+
rb_define_singleton_method(rb_cMagic, "do_not_stop_on_error", RUBY_METHOD_FUNC(rb_mgc_get_do_not_stop_on_error_global), 0);
|
1395
|
+
rb_define_singleton_method(rb_cMagic, "do_not_stop_on_error=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_stop_on_error_global), 1);
|
1396
|
+
|
1397
|
+
rb_define_singleton_method(rb_cMagic, "version", RUBY_METHOD_FUNC(rb_mgc_version), 0);
|
1398
|
+
|
1399
|
+
rb_define_method(rb_cMagic, "initialize", RUBY_METHOD_FUNC(rb_mgc_initialize), -2);
|
1400
|
+
|
1401
|
+
rb_define_method(rb_cMagic, "do_not_stop_on_error", RUBY_METHOD_FUNC(rb_mgc_get_do_not_stop_on_error), 0);
|
1402
|
+
rb_define_method(rb_cMagic, "do_not_stop_on_error=", RUBY_METHOD_FUNC(rb_mgc_set_do_not_stop_on_error), 1);
|
1403
|
+
|
1404
|
+
rb_define_method(rb_cMagic, "open?", RUBY_METHOD_FUNC(rb_mgc_open_p), 0);
|
1405
|
+
rb_define_method(rb_cMagic, "close", RUBY_METHOD_FUNC(rb_mgc_close), 0);
|
1406
|
+
rb_define_method(rb_cMagic, "closed?", RUBY_METHOD_FUNC(rb_mgc_close_p), 0);
|
1407
|
+
|
1408
|
+
rb_define_method(rb_cMagic, "paths", RUBY_METHOD_FUNC(rb_mgc_get_paths), 0);
|
1409
|
+
|
1410
|
+
rb_define_method(rb_cMagic, "get_parameter", RUBY_METHOD_FUNC(rb_mgc_get_parameter), 1);
|
1411
|
+
rb_define_method(rb_cMagic, "set_parameter", RUBY_METHOD_FUNC(rb_mgc_set_parameter), 2);
|
1412
|
+
|
1413
|
+
rb_define_method(rb_cMagic, "flags", RUBY_METHOD_FUNC(rb_mgc_get_flags), 0);
|
1414
|
+
rb_define_method(rb_cMagic, "flags=", RUBY_METHOD_FUNC(rb_mgc_set_flags), 1);
|
1415
|
+
|
1416
|
+
rb_define_method(rb_cMagic, "file", RUBY_METHOD_FUNC(rb_mgc_file), 1);
|
1417
|
+
rb_define_method(rb_cMagic, "buffer", RUBY_METHOD_FUNC(rb_mgc_buffer), 1);
|
1418
|
+
rb_define_method(rb_cMagic, "descriptor", RUBY_METHOD_FUNC(rb_mgc_descriptor), 1);
|
1419
|
+
|
1420
|
+
rb_alias(rb_cMagic, rb_intern("fd"), rb_intern("descriptor"));
|
1421
|
+
|
1422
|
+
rb_define_method(rb_cMagic, "load", RUBY_METHOD_FUNC(rb_mgc_load), -2);
|
1423
|
+
rb_define_method(rb_cMagic, "load_buffers", RUBY_METHOD_FUNC(rb_mgc_load_buffers), -2);
|
1424
|
+
rb_define_method(rb_cMagic, "loaded?", RUBY_METHOD_FUNC(rb_mgc_load_p), 0);
|
1425
|
+
|
1426
|
+
rb_alias(rb_cMagic, rb_intern("load_files"), rb_intern("load"));
|
1427
|
+
|
1428
|
+
rb_define_method(rb_cMagic, "compile", RUBY_METHOD_FUNC(rb_mgc_compile), 1);
|
1429
|
+
rb_define_method(rb_cMagic, "check", RUBY_METHOD_FUNC(rb_mgc_check), 1);
|
1430
|
+
|
1431
|
+
rb_alias(rb_cMagic, rb_intern("valid?"), rb_intern("check"));
|
1432
|
+
|
1433
|
+
/*
|
1434
|
+
* Controls how many levels of recursion will be followed for
|
1435
|
+
* indirect magic entries.
|
1436
|
+
*/
|
1437
|
+
MAGIC_DEFINE_PARAMETER(INDIR_MAX);
|
1438
|
+
/*
|
1439
|
+
* Controls the maximum number of calls for name or use magic.
|
1440
|
+
*/
|
1441
|
+
MAGIC_DEFINE_PARAMETER(NAME_MAX);
|
1442
|
+
/*
|
1443
|
+
* Controls how many ELF program sections will be processed.
|
1444
|
+
*/
|
1445
|
+
MAGIC_DEFINE_PARAMETER(ELF_PHNUM_MAX);
|
1446
|
+
/*
|
1447
|
+
* Controls how many ELF sections will be processed.
|
1448
|
+
*/
|
1449
|
+
MAGIC_DEFINE_PARAMETER(ELF_SHNUM_MAX);
|
1450
|
+
/*
|
1451
|
+
* Controls how many ELF notes will be processed.
|
1452
|
+
*/
|
1453
|
+
MAGIC_DEFINE_PARAMETER(ELF_NOTES_MAX);
|
1454
|
+
/*
|
1455
|
+
* Controls the length limit for regular expression searches.
|
1456
|
+
*/
|
1457
|
+
MAGIC_DEFINE_PARAMETER(REGEX_MAX);
|
1458
|
+
/*
|
1459
|
+
* Controls the maximum number of bytes to read from a file.
|
1460
|
+
*/
|
1461
|
+
MAGIC_DEFINE_PARAMETER(BYTES_MAX);
|
1462
|
+
/*
|
1463
|
+
* No special handling and/or flags specified. Default behavior.
|
1464
|
+
*/
|
1465
|
+
MAGIC_DEFINE_FLAG(NONE);
|
1466
|
+
/*
|
1467
|
+
* Print debugging messages to standard error output.
|
1468
|
+
*/
|
1469
|
+
MAGIC_DEFINE_FLAG(DEBUG);
|
1470
|
+
/*
|
1471
|
+
* If the file queried is a symbolic link, follow it.
|
1472
|
+
*/
|
1473
|
+
MAGIC_DEFINE_FLAG(SYMLINK);
|
1474
|
+
/*
|
1475
|
+
* If the file is compressed, unpack it and look at the contents.
|
1476
|
+
*/
|
1477
|
+
MAGIC_DEFINE_FLAG(COMPRESS);
|
1478
|
+
/*
|
1479
|
+
* If the file is a block or character special device, then open
|
1480
|
+
* the device and try to look at the contents.
|
1481
|
+
*/
|
1482
|
+
MAGIC_DEFINE_FLAG(DEVICES);
|
1483
|
+
/*
|
1484
|
+
* Return a MIME type string, instead of a textual description.
|
1485
|
+
*/
|
1486
|
+
MAGIC_DEFINE_FLAG(MIME_TYPE);
|
1487
|
+
/*
|
1488
|
+
* Return all matches, not just the first.
|
1489
|
+
*/
|
1490
|
+
MAGIC_DEFINE_FLAG(CONTINUE);
|
1491
|
+
/*
|
1492
|
+
* Check the Magic database for consistency and print warnings to
|
1493
|
+
* standard error output.
|
1494
|
+
*/
|
1495
|
+
MAGIC_DEFINE_FLAG(CHECK);
|
1496
|
+
/*
|
1497
|
+
* Attempt to preserve access time (atime, utime or utimes) of the
|
1498
|
+
* file queried on systems that support such system calls.
|
1499
|
+
*/
|
1500
|
+
MAGIC_DEFINE_FLAG(PRESERVE_ATIME);
|
1501
|
+
/*
|
1502
|
+
* Do not convert unprintable characters to an octal representation.
|
1503
|
+
*/
|
1504
|
+
MAGIC_DEFINE_FLAG(RAW);
|
1505
|
+
/*
|
1506
|
+
* Treat operating system errors while trying to open files and follow
|
1507
|
+
* symbolic links as first class errors, instead of storing them in the
|
1508
|
+
* Magic library error buffer for retrieval later.
|
1509
|
+
*/
|
1510
|
+
MAGIC_DEFINE_FLAG(ERROR);
|
1511
|
+
/*
|
1512
|
+
* Return a MIME encoding, instead of a textual description.
|
1513
|
+
*/
|
1514
|
+
MAGIC_DEFINE_FLAG(MIME_ENCODING);
|
1515
|
+
/*
|
1516
|
+
* A shorthand for using MIME_TYPE and MIME_ENCODING flags together.
|
1517
|
+
*/
|
1518
|
+
MAGIC_DEFINE_FLAG(MIME);
|
1519
|
+
/*
|
1520
|
+
* Return the Apple creator and type.
|
1521
|
+
*/
|
1522
|
+
MAGIC_DEFINE_FLAG(APPLE);
|
1523
|
+
/*
|
1524
|
+
* Do not look for, or inside compressed files.
|
1525
|
+
*/
|
1526
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_COMPRESS);
|
1527
|
+
/*
|
1528
|
+
* Do not look for, or inside tar archive files.
|
1529
|
+
*/
|
1530
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_TAR);
|
1531
|
+
/*
|
1532
|
+
* Do not consult Magic files.
|
1533
|
+
*/
|
1534
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_SOFT);
|
1535
|
+
/*
|
1536
|
+
* Check for EMX application type (only supported on EMX).
|
1537
|
+
*/
|
1538
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_APPTYPE);
|
1539
|
+
/*
|
1540
|
+
* Do not check for ELF files (do not examine ELF file details).
|
1541
|
+
*/
|
1542
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_ELF);
|
1543
|
+
/*
|
1544
|
+
* Do not check for various types of text files.
|
1545
|
+
*/
|
1546
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_TEXT);
|
1547
|
+
/*
|
1548
|
+
* Do not check for CDF files.
|
1549
|
+
*/
|
1550
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_CDF);
|
1551
|
+
/*
|
1552
|
+
* Do not check for CSV files.
|
1553
|
+
*/
|
1554
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_CSV);
|
1555
|
+
/*
|
1556
|
+
* Do not look for known tokens inside ASCII files.
|
1557
|
+
*/
|
1558
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_TOKENS);
|
1559
|
+
/*
|
1560
|
+
* Return a MIME encoding, instead of a textual description.
|
1561
|
+
*/
|
1562
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_ENCODING);
|
1563
|
+
/*
|
1564
|
+
* Do not check for JSON files.
|
1565
|
+
*/
|
1566
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_JSON);
|
1567
|
+
/*
|
1568
|
+
* Do not use built-in tests; only consult the Magic file.
|
1569
|
+
*/
|
1570
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_BUILTIN);
|
1571
|
+
/*
|
1572
|
+
* Do not check for various types of text files, same as NO_CHECK_TEXT.
|
1573
|
+
*/
|
1574
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_ASCII);
|
1575
|
+
/*
|
1576
|
+
* Do not look for Fortran sequences inside ASCII files.
|
1577
|
+
*/
|
1578
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_FORTRAN);
|
1579
|
+
/*
|
1580
|
+
* Do not look for troff sequences inside ASCII files.
|
1581
|
+
*/
|
1582
|
+
MAGIC_DEFINE_FLAG(NO_CHECK_TROFF);
|
1583
|
+
/*
|
1584
|
+
* Return a slash-separated list of extensions for this file type.
|
1585
|
+
*/
|
1586
|
+
MAGIC_DEFINE_FLAG(EXTENSION);
|
1587
|
+
/*
|
1588
|
+
* Do not report on compression, only report about the uncompressed data.
|
1589
|
+
*/
|
1590
|
+
MAGIC_DEFINE_FLAG(COMPRESS_TRANSP);
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
#if defined(__cplusplus)
|
1594
|
+
}
|
1595
|
+
#endif
|