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.
@@ -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