ruby-magic-static 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,307 @@
1
+ #if !defined(_RUBY_MAGIC_H)
2
+ #define _RUBY_MAGIC_H 1
3
+
4
+ #if defined(__cplusplus)
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include "common.h"
9
+ #include "functions.h"
10
+
11
+ #define MAGIC_SYNCHRONIZED(f, d) magic_lock(object, (f), (d))
12
+
13
+ #define MAGIC_OBJECT(o) \
14
+ Data_Get_Struct(object, magic_object_t, (o))
15
+
16
+ #define MAGIC_COOKIE(o, c) \
17
+ ((c) = MAGIC_OBJECT((o))->cookie)
18
+
19
+ #define MAGIC_CLOSED_P(o) RTEST(rb_mgc_close_p((o)))
20
+ #define MAGIC_LOADED_P(o) RTEST(rb_mgc_load_p((o)))
21
+
22
+ #define MAGIC_WARNING(i, ...) \
23
+ do { \
24
+ if (!(i) || !(rb_mgc_warning & BIT(i))) { \
25
+ rb_mgc_warning |= BIT(i); \
26
+ rb_warn(__VA_ARGS__); \
27
+ } \
28
+ } while(0)
29
+
30
+ #define MAGIC_ARGUMENT_TYPE_ERROR(o, ...) \
31
+ rb_raise(rb_eTypeError, error(E_ARGUMENT_TYPE_INVALID), CLASS_NAME((o)), __VA_ARGS__)
32
+
33
+ #define MAGIC_GENERIC_ERROR(k, e, m) \
34
+ rb_exc_raise(magic_generic_error((k), (e), error(m)))
35
+
36
+ #define MAGIC_LIBRARY_ERROR(c) \
37
+ rb_exc_raise(magic_library_error(rb_mgc_eMagicError, (c)))
38
+
39
+ #define MAGIC_CHECK_INTEGER_TYPE(o) magic_check_type((o), T_FIXNUM)
40
+ #define MAGIC_CHECK_STRING_TYPE(o) magic_check_type((o), T_STRING)
41
+
42
+ #define MAGIC_CHECK_ARGUMENT_MISSING(t, o) \
43
+ do { \
44
+ if ((t) < (o)) \
45
+ rb_raise(rb_eArgError, error(E_ARGUMENT_MISSING), (t), (o)); \
46
+ } while(0)
47
+
48
+ #define MAGIC_CHECK_ARRAY_EMPTY(o) \
49
+ do { \
50
+ if (RARRAY_EMPTY_P(o)) \
51
+ rb_raise(rb_eArgError, "%s", error(E_ARGUMENT_TYPE_ARRAY_EMPTY)); \
52
+ } while(0)
53
+
54
+ #define MAGIC_CHECK_ARRAY_OF_STRINGS(o) \
55
+ magic_check_type_array_of_strings((o))
56
+
57
+ #define MAGIC_CHECK_OPEN(o) \
58
+ do { \
59
+ if (MAGIC_CLOSED_P(o)) \
60
+ MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError, EFAULT, \
61
+ E_MAGIC_LIBRARY_CLOSED); \
62
+ } while(0)
63
+
64
+ #define MAGIC_CHECK_LOADED(o) \
65
+ do { \
66
+ if (!MAGIC_LOADED_P(o)) \
67
+ MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EFAULT, \
68
+ E_MAGIC_LIBRARY_NOT_LOADED); \
69
+ } while(0)
70
+
71
+ #define MAGIC_STRINGIFY(s) #s
72
+
73
+ #define MAGIC_DEFINE_FLAG(c) \
74
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(c), INT2NUM(MAGIC_##c));
75
+
76
+ #define MAGIC_DEFINE_PARAMETER(c) \
77
+ rb_define_const(rb_cMagic, MAGIC_STRINGIFY(PARAM_##c), INT2NUM(MAGIC_PARAM_##c));
78
+
79
+ #define error(t) errors[(t)]
80
+
81
+ enum error {
82
+ E_UNKNOWN = 0,
83
+ E_NOT_ENOUGH_MEMORY,
84
+ E_ARGUMENT_MISSING,
85
+ E_ARGUMENT_TYPE_INVALID,
86
+ E_ARGUMENT_TYPE_ARRAY_EMPTY,
87
+ E_ARGUMENT_TYPE_ARRAY_STRINGS,
88
+ E_MAGIC_LIBRARY_INITIALIZE,
89
+ E_MAGIC_LIBRARY_CLOSED,
90
+ E_MAGIC_LIBRARY_NOT_LOADED,
91
+ E_PARAM_INVALID_TYPE,
92
+ E_PARAM_INVALID_VALUE,
93
+ E_FLAG_NOT_IMPLEMENTED,
94
+ E_FLAG_INVALID_TYPE
95
+ };
96
+
97
+ typedef struct parameter {
98
+ size_t value;
99
+ int tag;
100
+ } parameter_t;
101
+
102
+ typedef union file {
103
+ const char *path;
104
+ int fd;
105
+ } file_t;
106
+
107
+ typedef struct buffers {
108
+ size_t count;
109
+ size_t *sizes;
110
+ void **pointers;
111
+ } buffers_t;
112
+
113
+ typedef struct magic_object {
114
+ magic_t cookie;
115
+ VALUE mutex;
116
+ unsigned int database_loaded:1;
117
+ unsigned int stop_on_errors:1;
118
+ } magic_object_t;
119
+
120
+ typedef struct magic_arguments {
121
+ union {
122
+ file_t file;
123
+ parameter_t parameter;
124
+ buffers_t buffers;
125
+ } type;
126
+ magic_t cookie;
127
+ const char *result;
128
+ int flags;
129
+ int status;
130
+ unsigned int stop_on_errors:1;
131
+ } magic_arguments_t;
132
+
133
+ typedef struct magic_exception {
134
+ const char *magic_error;
135
+ VALUE klass;
136
+ int magic_errno;
137
+ } magic_exception_t;
138
+
139
+ static const char *errors[] = {
140
+ [E_UNKNOWN] = "an unknown error has occurred",
141
+ [E_NOT_ENOUGH_MEMORY] = "cannot allocate memory",
142
+ [E_ARGUMENT_MISSING] = "wrong number of arguments (given %d, expected %d)",
143
+ [E_ARGUMENT_TYPE_INVALID] = "wrong argument type %s (expected %s)",
144
+ [E_ARGUMENT_TYPE_ARRAY_EMPTY] = "arguments list cannot be empty (expected array of String)",
145
+ [E_ARGUMENT_TYPE_ARRAY_STRINGS] = "wrong argument type %s in arguments list (expected String)",
146
+ [E_MAGIC_LIBRARY_INITIALIZE] = "failed to initialize Magic library",
147
+ [E_MAGIC_LIBRARY_CLOSED] = "Magic library is not open",
148
+ [E_MAGIC_LIBRARY_NOT_LOADED] = "Magic library not loaded",
149
+ [E_PARAM_INVALID_TYPE] = "unknown or invalid parameter specified",
150
+ [E_PARAM_INVALID_VALUE] = "invalid parameter value specified",
151
+ [E_FLAG_NOT_IMPLEMENTED] = "flag is not implemented",
152
+ [E_FLAG_INVALID_TYPE] = "unknown or invalid flag specified",
153
+ NULL
154
+ };
155
+
156
+ static inline VALUE
157
+ magic_shift(VALUE v)
158
+ {
159
+ return ARRAY_P(v) ? \
160
+ rb_funcall(v, rb_intern("shift"), 0, Qundef) : \
161
+ Qnil;
162
+ }
163
+
164
+ static inline VALUE
165
+ magic_split(VALUE a, VALUE b)
166
+ {
167
+ return (STRING_P(a) && STRING_P(b)) ? \
168
+ rb_funcall(a, rb_intern("split"), 1, b) : \
169
+ Qnil;
170
+ }
171
+
172
+ static inline VALUE
173
+ magic_join(VALUE a, VALUE b)
174
+ {
175
+ return (ARRAY_P(a) && STRING_P(b)) ? \
176
+ rb_funcall(a, rb_intern("join"), 1, b) : \
177
+ Qnil;
178
+ }
179
+
180
+ static inline VALUE
181
+ magic_flatten(VALUE v)
182
+ {
183
+ return ARRAY_P(v) ? \
184
+ rb_funcall(v, rb_intern("flatten"), 0, Qundef) : \
185
+ Qnil;
186
+ }
187
+
188
+ static int
189
+ magic_fileno(VALUE object)
190
+ {
191
+ int fd;
192
+ rb_io_t *io;
193
+
194
+ if (rb_respond_to(object, rb_intern("fileno"))) {
195
+ object = rb_funcall(object, rb_intern("fileno"), 0, Qundef);
196
+ return NUM2INT(object);
197
+ }
198
+
199
+ if (!FILE_P(object))
200
+ object = rb_convert_type(object, T_FILE, "IO", "to_io");
201
+
202
+ GetOpenFile(object, io);
203
+ if ((fd = FPTR_TO_FD(io)) < 0)
204
+ rb_raise(rb_eIOError, "closed stream");
205
+
206
+ return fd;
207
+ }
208
+
209
+ static inline VALUE
210
+ magic_path(VALUE object)
211
+ {
212
+ if (STRING_P(object))
213
+ return object;
214
+
215
+ if (rb_respond_to(object, rb_intern("to_path")))
216
+ return rb_funcall(object, rb_intern("to_path"), 0, Qundef);
217
+
218
+ if (rb_respond_to(object, rb_intern("path")))
219
+ return rb_funcall(object, rb_intern("path"), 0, Qundef);
220
+
221
+ if (rb_respond_to(object, rb_intern("to_s")))
222
+ return rb_funcall(object, rb_intern("to_s"), 0, Qundef);
223
+
224
+ return Qnil;
225
+ }
226
+
227
+ static inline void
228
+ magic_check_type(VALUE object, int type)
229
+ {
230
+ VALUE boolean = Qundef;
231
+
232
+ boolean = rb_obj_is_kind_of(object, T_INTEGER);
233
+ if (type == T_FIXNUM && !RVAL2CBOOL(boolean))
234
+ MAGIC_ARGUMENT_TYPE_ERROR(object, rb_class2name(T_INTEGER));
235
+
236
+ Check_Type(object, type);
237
+ }
238
+
239
+ static inline void
240
+ magic_check_type_array_of_strings(VALUE object)
241
+ {
242
+ VALUE value = Qundef;
243
+
244
+ for (int i = 0; i < RARRAY_LEN(object); i++) {
245
+ value = RARRAY_AREF(object, (long)i);
246
+ if (NIL_P(value) || !STRING_P(value))
247
+ rb_raise(rb_eTypeError,
248
+ error(E_ARGUMENT_TYPE_ARRAY_STRINGS),
249
+ CLASS_NAME(value));
250
+ }
251
+ }
252
+
253
+ RUBY_EXTERN ID id_at_flags;
254
+ RUBY_EXTERN ID id_at_paths;
255
+
256
+ RUBY_EXTERN VALUE rb_cMagic;
257
+
258
+ RUBY_EXTERN VALUE rb_mgc_eError;
259
+ RUBY_EXTERN VALUE rb_mgc_eMagicError;
260
+ RUBY_EXTERN VALUE rb_mgc_eLibraryError;
261
+ RUBY_EXTERN VALUE rb_mgc_eParameterError;
262
+ RUBY_EXTERN VALUE rb_mgc_eFlagsError;
263
+ RUBY_EXTERN VALUE rb_mgc_eNotImplementedError;
264
+
265
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_auto_load_global(VALUE object);
266
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_auto_load_global(VALUE object,
267
+ VALUE value);
268
+
269
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_stop_on_error_global(VALUE object);
270
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_stop_on_error_global(VALUE object,
271
+ VALUE value);
272
+
273
+ RUBY_EXTERN VALUE rb_mgc_initialize(VALUE object, VALUE arguments);
274
+
275
+ RUBY_EXTERN VALUE rb_mgc_get_do_not_stop_on_error(VALUE object);
276
+ RUBY_EXTERN VALUE rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value);
277
+
278
+ RUBY_EXTERN VALUE rb_mgc_open_p(VALUE object);
279
+ RUBY_EXTERN VALUE rb_mgc_close(VALUE object);
280
+ RUBY_EXTERN VALUE rb_mgc_close_p(VALUE object);
281
+
282
+ RUBY_EXTERN VALUE rb_mgc_get_paths(VALUE object);
283
+
284
+ RUBY_EXTERN VALUE rb_mgc_get_parameter(VALUE object, VALUE tag);
285
+ RUBY_EXTERN VALUE rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value);
286
+
287
+ RUBY_EXTERN VALUE rb_mgc_get_flags(VALUE object);
288
+ RUBY_EXTERN VALUE rb_mgc_set_flags(VALUE object, VALUE value);
289
+
290
+ RUBY_EXTERN VALUE rb_mgc_load(VALUE object, VALUE arguments);
291
+ RUBY_EXTERN VALUE rb_mgc_load_buffers(VALUE object, VALUE arguments);
292
+ RUBY_EXTERN VALUE rb_mgc_load_p(VALUE object);
293
+
294
+ RUBY_EXTERN VALUE rb_mgc_compile(VALUE object, VALUE arguments);
295
+ RUBY_EXTERN VALUE rb_mgc_check(VALUE object, VALUE arguments);
296
+
297
+ RUBY_EXTERN VALUE rb_mgc_file(VALUE object, VALUE value);
298
+ RUBY_EXTERN VALUE rb_mgc_buffer(VALUE object, VALUE value);
299
+ RUBY_EXTERN VALUE rb_mgc_descriptor(VALUE object, VALUE value);
300
+
301
+ RUBY_EXTERN VALUE rb_mgc_version(VALUE object);
302
+
303
+ #if defined(__cplusplus)
304
+ }
305
+ #endif
306
+
307
+ #endif /* _RUBY_MAGIC_H */
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEIDCCAoigAwIBAgIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJrdy9E
3
+ Qz1saW51eC9EQz1jb20wHhcNMjEwMTAxMDAwOTU0WhcNMjYwMTAxMDAwOTU0WjAd
4
+ MRswGQYDVQQDDBJrdy9EQz1saW51eC9EQz1jb20wggGiMA0GCSqGSIb3DQEBAQUA
5
+ A4IBjwAwggGKAoIBgQCv02+pOrAMVUipLY7qjNLx8OMfMjnVCBH21SsWn8gyIHE9
6
+ BtQ+tlsJU8nWNjlr++7SKIV5vQmyYsC2UY0cdcFASdoV0A3Lc2Z0makfvPgcIlpL
7
+ 5THqQtP11tJfhjQ3MSFJYRG2D6m6GNqA+WTTsvJbPIxy5PHv5xb+79LLzcVxB9Op
8
+ C0ervTOF8W6Ye4EDvhQ5tppOr/d26UQV+8zRuxjxx5uZSPfUrE9u/gIIdeROoB3T
9
+ cnjAfzvjIzampLQppvhUnT4Vf5Rum2LohZ5GosKLy7tM65vr1eLyI2ndvS1MXWrU
10
+ 05sFKm5CSqORD+TVkR1jd3z5HdPgO1KwadccxFixoI8kEIt/iixWTzbka2T2iJoq
11
+ 5DeNMEMYYAZKuAGBzBcgvgPccCeAXFVF9AHjfaGRUMmYNHKK2HD6AdgNdhcE18V+
12
+ CJxFtggCJFYc1ygFOsHZPTbKo9+3ybSQhAswtDosWt26utUT1JOc2Bkj1sgQ0Yrk
13
+ orANsdYz2ee3JFkzx08CAwEAAaNrMGkwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
14
+ HQYDVR0OBBYEFME41mMBb/XAHgjhlX4kE8xnXxewMBcGA1UdEQQQMA6BDGt3QGxp
15
+ bnV4LmNvbTAXBgNVHRIEEDAOgQxrd0BsaW51eC5jb20wDQYJKoZIhvcNAQELBQAD
16
+ ggGBAF/2ryrSgTpf0+wYG46Oi6V3p9A3uMxxbGsh0ZmlLQT1Z1ozclR+xzxzyIFC
17
+ i7YWYyR085brDBnYNXgnUT9Nm4iAYx58MaPD28IFrcX0XA3DJE6Wkx4MmMV0chiJ
18
+ kf5ASikfGtFtf9qDmpLQB4louB6HpKNq1MwsQo8zwY93t77HCiV5f0g43rcZfGTn
19
+ wfBhpT7oOVWgfTLeBD811aS52VUCWclmnz+f01GdTeMwqsgc6oJaPSvg4JCMN94O
20
+ wcBlxus69rhM8PeTJNhwLxzRCNnZ69t9k2cU+4lTmQQIB8gnEFJxY9gZdgQ6pej0
21
+ HXUIut+6pp5BRYF2mTZ3fnxhWyIZaeB7lla2gI6rV2GXDbp4kVplGEuQ975YklJw
22
+ i4y7bz2Es4Hkly2Nc/J2L0+uMoBhMWMY3Xl0XDdkZYtBdnSB5g7NacChaAsukEkd
23
+ Ozt6vfXxSzW/KfodB+0ELjlHWiFbI8w7c8Kt7/ceZGVsXTxD/f4tVWy8MmxFy3pY
24
+ Cpe8Kg==
25
+ -----END CERTIFICATE-----
data/lib/magic.rb ADDED
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'magic/magic'
4
+ require_relative 'magic/version'
5
+ require_relative 'magic/core/file'
6
+ require_relative 'magic/core/string'
7
+
8
+ #
9
+ # File _Magic_ in Ruby.
10
+ #
11
+ # Simple interface to _libmagic_ for Ruby Programming Language.
12
+ #
13
+ class Magic
14
+ #
15
+ # call-seq:
16
+ # magic.inspect -> string
17
+ #
18
+ # Example:
19
+ #
20
+ # magic = Magic.new
21
+ # magic.inspect #=> "#<Magic:0x007fd5258a1108 @flags=0, @paths=[\"/etc/magic\", \"/usr/share/misc/magic\"]>"
22
+ # magic.close
23
+ # magic.inspect #=> "#<Magic:0x007fd5258a1108 @flags=0, @paths=[\"/etc/magic\", \"/usr/share/misc/magic\"] (closed)>"
24
+ #
25
+ def inspect
26
+ super.insert(-2, self.closed? ? ' (closed)' : '')
27
+ end
28
+
29
+ #
30
+ # call-seq:
31
+ # magic.flags_list( boolean ) -> array
32
+ #
33
+ # See also: Magic#flags and Magic#flags_names
34
+ #
35
+ def flags_list(names = false)
36
+ raise LibraryError, 'Magic library is not open' if closed?
37
+ return [names ? 'NONE' : 0] if @flags.zero?
38
+
39
+ n, i = 0, @flags
40
+ flags = []
41
+
42
+ @@flags_map ||= flags_as_map if names
43
+
44
+ while i > 0
45
+ n = 2 ** (Math.log(i) / Math.log(2)).to_i
46
+ i = i - n
47
+ flags.insert(0, names ? @@flags_map[n] : n)
48
+ end
49
+
50
+ flags
51
+ end
52
+
53
+ alias_method :flags_to_a, :flags_list
54
+
55
+ # call-seq:
56
+ # magic.flags_names -> array
57
+ #
58
+ # See also: Magic#flags and Magic#flags_list
59
+ #
60
+ def flags_names
61
+ flags_list(true)
62
+ end
63
+
64
+ class << self
65
+ #
66
+ # call-seq:
67
+ # Magic.open( integer ) -> self
68
+ # Magic.open( integer ) {|magic| block } -> string or array
69
+ #
70
+ # See also: Magic::mime, Magic::type, Magic::encoding, Magic::compile and Magic::check
71
+ #
72
+ def open(flags = Magic::NONE)
73
+ magic = Magic.new
74
+ magic.flags = flags
75
+
76
+ if block_given?
77
+ begin
78
+ yield magic
79
+ ensure
80
+ magic.close
81
+ end
82
+ else
83
+ magic
84
+ end
85
+ end
86
+
87
+ #
88
+ # call-seq:
89
+ # Magic.mime -> self
90
+ # Magic.mime {|magic| block } -> string or array
91
+ #
92
+ # See also: Magic::open, Magic::type, Magic::encoding, Magic::compile and Magic::check
93
+ #
94
+ def mime(&block)
95
+ open(Magic::MIME, &block)
96
+ end
97
+
98
+ #
99
+ # call-seq:
100
+ # Magic.type -> self
101
+ # Magic.type {|magic| block } -> string or array
102
+ #
103
+ # See also: Magic::open, Magic::mime, Magic::encoding, Magic::compile and Magic::check
104
+ #
105
+ def type(&block)
106
+ open(Magic::MIME_TYPE, &block)
107
+ end
108
+
109
+ #
110
+ # call-seq:
111
+ # Magic.encoding -> self
112
+ # Magic.encoding {|magic| block } -> string or array
113
+ #
114
+ # See also: Magic::open, Magic::mime, Magic::type, Magic::compile and Magic::check
115
+ #
116
+ def encoding(&block)
117
+ open(Magic::MIME_ENCODING, &block)
118
+ end
119
+
120
+ #
121
+ # call-seq:
122
+ # Magic.compile( string, ... ) -> true
123
+ # Magic.compile( array ) -> true
124
+ #
125
+ # See also: Magic::open, Magic::mime, Magic::type, Magic::encoding, and Magic::check
126
+ #
127
+ def compile(*paths)
128
+ open {|m| m.compile(paths) }
129
+ end
130
+
131
+ #
132
+ # call-seq:
133
+ # Magic.check( string, ... ) -> true or false
134
+ # Magic.check( array ) -> true or false
135
+ #
136
+ # See also: Magic::open, Magic::mime, Magic::type, Magic::encoding and Magic::compile
137
+ #
138
+ def check(*paths)
139
+ open {|m| m.check(paths) }
140
+ end
141
+
142
+ #
143
+ # call-seq:
144
+ # Magic.file( object ) -> string or array
145
+ # Magic.file( string ) -> string or array
146
+ # Magic.file( string, integer ) -> string or array
147
+ #
148
+ # See also:
149
+ #
150
+ def file(path, flags = Magic::MIME)
151
+ open(flags).file(path)
152
+ end
153
+
154
+ #
155
+ # call-seq:
156
+ # Magic.buffer( string ) -> string or array
157
+ # Magic.buffer( string, integer ) -> string or array
158
+ #
159
+ # See also:
160
+ #
161
+ def buffer(buffer, flags = Magic::MIME)
162
+ open(flags).buffer(buffer)
163
+ end
164
+
165
+ #
166
+ # call-seq:
167
+ # Magic.descriptor( object ) -> string or array
168
+ # Magic.descriptor( integer ) -> string or array
169
+ # Magic.descriptor( integer, integer ) -> string or array
170
+ #
171
+ # See also:
172
+ #
173
+ def descriptor(fd, flags = Magic::MIME)
174
+ open(flags).descriptor(fd)
175
+ end
176
+
177
+ alias_method :fd, :descriptor
178
+ end
179
+
180
+ private
181
+
182
+ def power_of_two?(number)
183
+ number > 0 && Math.log2(number) % 1 == 0
184
+ end
185
+
186
+ def flags_as_map
187
+ klass = self.class
188
+
189
+ klass.constants.each_with_object({}) do |constant, flags|
190
+ constant = constant.to_s
191
+
192
+ next if constant.start_with?('PARAM_')
193
+
194
+ value = klass.const_get(constant)
195
+
196
+ if value.is_a?(Integer) && power_of_two?(value)
197
+ flags[value] = constant
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ FileMagic = Magic