ruby-filemagic 0.6.2-x86-mingw32
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/ChangeLog +92 -0
- data/README +101 -0
- data/Rakefile +34 -0
- data/TODO +7 -0
- data/ext/filemagic/extconf.rb +16 -0
- data/ext/filemagic/filemagic.c +310 -0
- data/ext/filemagic/filemagic.h +98 -0
- data/lib/filemagic/1.9/ruby_filemagic.so +0 -0
- data/lib/filemagic/2.0/ruby_filemagic.so +0 -0
- data/lib/filemagic/2.1/ruby_filemagic.so +0 -0
- data/lib/filemagic/2.2/ruby_filemagic.so +0 -0
- data/lib/filemagic/ext.rb +99 -0
- data/lib/filemagic/magic.mgc +0 -0
- data/lib/filemagic/version.rb +27 -0
- data/lib/filemagic.rb +142 -0
- data/lib/ruby-filemagic.rb +1 -0
- data/test/excel-example.xls +0 -0
- data/test/filemagic_test.rb +227 -0
- data/test/leaktest.rb +16 -0
- data/test/mahoro.c +187 -0
- data/test/perl +19 -0
- data/test/perl.mgc +0 -0
- data/test/pyfile +1 -0
- data/test/pyfile-compressed.gz +0 -0
- data/test/pylink +1 -0
- metadata +148 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'filemagic'
|
2
|
+
|
3
|
+
module FileMagic::Ext
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval {
|
7
|
+
extend ClassMethods
|
8
|
+
include InstanceMethods
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
|
14
|
+
def file_type(file, *flags)
|
15
|
+
raise NotImplementedError, 'must be implemented by including class'
|
16
|
+
end
|
17
|
+
|
18
|
+
def file(file, *flags)
|
19
|
+
file_type(file, *flags)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mime_type(file, *flags)
|
23
|
+
file_type(file, *flags.unshift(:mime))
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :mime, :mime_type
|
27
|
+
|
28
|
+
def content_type(file, *flags)
|
29
|
+
mime_type(file, *flags << { simplified: true })
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
module InstanceMethods
|
35
|
+
|
36
|
+
def file_type(*flags)
|
37
|
+
self.class.file_type(self, *flags)
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :file, :file_type
|
41
|
+
|
42
|
+
def mime_type(*flags)
|
43
|
+
self.class.mime_type(self, *flags)
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :mime, :mime_type
|
47
|
+
|
48
|
+
def content_type(*flags)
|
49
|
+
self.class.content_type(self, *flags)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class File
|
57
|
+
|
58
|
+
include FileMagic::Ext
|
59
|
+
|
60
|
+
def self.file_type(file, *flags)
|
61
|
+
FileMagic.fm(*flags).file(file.respond_to?(:path) ? file.path : file)
|
62
|
+
rescue FileMagic::FileMagicError
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class String
|
68
|
+
|
69
|
+
include FileMagic::Ext
|
70
|
+
|
71
|
+
def self.file_type(string, *flags)
|
72
|
+
FileMagic.fm(*flags).buffer(string)
|
73
|
+
rescue FileMagic::FileMagicError
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
if $0 == __FILE__
|
79
|
+
f = __FILE__
|
80
|
+
p f
|
81
|
+
|
82
|
+
p File.file_type(f)
|
83
|
+
p File.mime_type(f)
|
84
|
+
p File.content_type(f)
|
85
|
+
|
86
|
+
f = File.new(f)
|
87
|
+
p f
|
88
|
+
|
89
|
+
p f.file_type
|
90
|
+
p f.mime_type
|
91
|
+
p f.content_type
|
92
|
+
|
93
|
+
s = '#! /usr/bin/ruby'
|
94
|
+
p s
|
95
|
+
|
96
|
+
p s.file_type
|
97
|
+
p s.mime_type
|
98
|
+
p s.content_type
|
99
|
+
end
|
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class FileMagic
|
2
|
+
|
3
|
+
module Version
|
4
|
+
|
5
|
+
MAJOR = 0
|
6
|
+
MINOR = 6
|
7
|
+
TINY = 2
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# Returns array representation.
|
12
|
+
def to_a
|
13
|
+
[MAJOR, MINOR, TINY]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Short-cut for version string.
|
17
|
+
def to_s
|
18
|
+
to_a.join('.')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
VERSION = Version.to_s
|
26
|
+
|
27
|
+
end
|
data/lib/filemagic.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
begin
|
2
|
+
require "filemagic/#{RUBY_VERSION[/\d+.\d+/]}/ruby_filemagic"
|
3
|
+
rescue LoadError => err
|
4
|
+
raise if err.respond_to?(:path) && !err.path
|
5
|
+
require 'filemagic/ruby_filemagic'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'filemagic/version'
|
9
|
+
|
10
|
+
class FileMagic
|
11
|
+
|
12
|
+
DEFAULT_MAGIC = __FILE__.sub(/\.rb\z/, '/magic.mgc')
|
13
|
+
|
14
|
+
ENV['MAGIC'] ||= DEFAULT_MAGIC unless path
|
15
|
+
|
16
|
+
# Map flag names to their values (:name => Integer).
|
17
|
+
FLAGS_BY_SYM = [
|
18
|
+
:none, # No flags
|
19
|
+
:debug, # Turn on debugging
|
20
|
+
:symlink, # Follow symlinks
|
21
|
+
:compress, # Check inside compressed files
|
22
|
+
:devices, # Look at the contents of devices
|
23
|
+
:mime_type, # Return only the MIME type
|
24
|
+
:continue, # Return all matches
|
25
|
+
:check, # Print warnings to stderr
|
26
|
+
:preserve_atime, # Restore access time on exit
|
27
|
+
:raw, # Don't translate unprint chars
|
28
|
+
:error, # Handle ENOENT etc as real errors
|
29
|
+
:mime_encoding, # Return only the MIME encoding
|
30
|
+
:mime, # MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING
|
31
|
+
:apple, # Return the Apple creator and type
|
32
|
+
:no_check_compress, # Don't check for compressed files
|
33
|
+
:no_check_tar, # Don't check for tar files
|
34
|
+
:no_check_soft, # Don't check magic entries
|
35
|
+
:no_check_apptype, # Don't check application type
|
36
|
+
:no_check_elf, # Don't check for elf details
|
37
|
+
:no_check_text, # Don't check for text files
|
38
|
+
:no_check_cdf, # Don't check for cdf files
|
39
|
+
:no_check_tokens, # Don't check ascii/tokens
|
40
|
+
:no_check_encoding, # Don't check text encodings
|
41
|
+
:no_check_builtin, # No built-in tests; only consult the magic file
|
42
|
+
|
43
|
+
# Defined for backwards compatibility (renamed)
|
44
|
+
:no_check_ascii, # MAGIC_NO_CHECK_TEXT
|
45
|
+
|
46
|
+
# Defined for backwards compatibility; do nothing
|
47
|
+
:no_check_fortran, # Don't check ascii/fortran
|
48
|
+
:no_check_troff # Don't check ascii/troff
|
49
|
+
].inject({}) { |flags, flag|
|
50
|
+
const = "MAGIC_#{flag.to_s.upcase}"
|
51
|
+
flags.update(flag => const_defined?(const) && const_get(const))
|
52
|
+
}
|
53
|
+
|
54
|
+
# Map flag values to their names (Integer => :name).
|
55
|
+
FLAGS_BY_INT = FLAGS_BY_SYM.invert.update(0 => :none)
|
56
|
+
|
57
|
+
# Extract "simple" MIME type.
|
58
|
+
SIMPLE_RE = %r{([.\w\/-]+)}
|
59
|
+
|
60
|
+
@fm = {}
|
61
|
+
|
62
|
+
class << self
|
63
|
+
|
64
|
+
# Provide a "magic singleton".
|
65
|
+
def fm(*flags)
|
66
|
+
options = flags.last.is_a?(Hash) ? flags.pop : {}
|
67
|
+
|
68
|
+
if fm = @fm[key = [flags = flags(flags), options]]
|
69
|
+
return fm unless fm.closed?
|
70
|
+
end
|
71
|
+
|
72
|
+
@fm[key] = new(flags, options)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Clear our instance cache.
|
76
|
+
def clear!
|
77
|
+
@fm.each_value(&:close).clear
|
78
|
+
end
|
79
|
+
|
80
|
+
# Just like #new, but takes an optional block, in which case #close
|
81
|
+
# is called at the end and the value of the block is returned.
|
82
|
+
def open(*flags)
|
83
|
+
fm = new(*flags)
|
84
|
+
|
85
|
+
if block_given?
|
86
|
+
begin
|
87
|
+
yield fm
|
88
|
+
ensure
|
89
|
+
fm.close
|
90
|
+
end
|
91
|
+
else
|
92
|
+
fm
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Just a short-cut to #open with the +mime+ flag set.
|
97
|
+
def mime(*flags, &block)
|
98
|
+
open(:mime, *flags, &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def magic_version(default = MAGIC_VERSION)
|
102
|
+
default != '0' ? default :
|
103
|
+
user_magic_version ||
|
104
|
+
auto_magic_version ||
|
105
|
+
[default, 'unknown']
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def user_magic_version(key = 'MAGIC_VERSION')
|
111
|
+
[ENV[key], 'user-specified'] if ENV[key]
|
112
|
+
end
|
113
|
+
|
114
|
+
def auto_magic_version
|
115
|
+
require 'nuggets/file/which'
|
116
|
+
|
117
|
+
if cmd = File.which_command([
|
118
|
+
'dpkg-query -f \'${Version}\' -W libmagic-dev',
|
119
|
+
'file -v'
|
120
|
+
])
|
121
|
+
[%x{#{cmd}}[/\d+\.\d+/], 'auto-detected']
|
122
|
+
end
|
123
|
+
rescue LoadError
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
attr_writer :simplified
|
129
|
+
|
130
|
+
def simplified?
|
131
|
+
@simplified
|
132
|
+
end
|
133
|
+
|
134
|
+
def io(io, length = 8)
|
135
|
+
buffer(io.read(length))
|
136
|
+
end
|
137
|
+
|
138
|
+
def inspect
|
139
|
+
super.insert(-2, closed? ? ' (closed)' : '')
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'filemagic'
|
Binary file
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'filemagic'
|
3
|
+
|
4
|
+
class TestFileMagic < Test::Unit::TestCase
|
5
|
+
|
6
|
+
magic_version, origin = FileMagic.magic_version
|
7
|
+
MAGIC_VERSION = magic_version.to_f
|
8
|
+
|
9
|
+
warn <<-EOT
|
10
|
+
|
11
|
+
libmagic version: #{MAGIC_VERSION}#{" (#{origin})" if origin}
|
12
|
+
magic file from #{FileMagic.path}
|
13
|
+
|
14
|
+
EOT
|
15
|
+
|
16
|
+
def test_file
|
17
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
18
|
+
|
19
|
+
python_script = match_version(
|
20
|
+
0 => 'a python script, ASCII text executable',
|
21
|
+
5.11 => 'Python script, ASCII text executable'
|
22
|
+
)
|
23
|
+
|
24
|
+
res = fm.file(path_to('pyfile'))
|
25
|
+
assert_equal(python_script, res)
|
26
|
+
|
27
|
+
if File.symlink?(path_to('pylink'))
|
28
|
+
res = fm.file(path_to('pylink'))
|
29
|
+
assert_equal("symbolic link to `pyfile'", res.strip)
|
30
|
+
end
|
31
|
+
|
32
|
+
fm.close
|
33
|
+
fm = FileMagic.new(FileMagic::MAGIC_SYMLINK)
|
34
|
+
|
35
|
+
res = fm.file(path_to('pylink'))
|
36
|
+
assert_equal(python_script, res)
|
37
|
+
|
38
|
+
fm.close
|
39
|
+
fm = FileMagic.new(FileMagic::MAGIC_SYMLINK | FileMagic::MAGIC_MIME)
|
40
|
+
|
41
|
+
res = fm.file(path_to('pylink'))
|
42
|
+
assert_equal('text/plain; charset=us-ascii', res)
|
43
|
+
|
44
|
+
fm.close
|
45
|
+
fm = FileMagic.new(FileMagic::MAGIC_COMPRESS)
|
46
|
+
|
47
|
+
res = fm.file(path_to('pyfile-compressed.gz'))
|
48
|
+
gzip_compressed = 'gzip compressed data, was "pyfile-compressed"'
|
49
|
+
assert_match(Gem.win_platform? ? /^#{gzip_compressed}/ :
|
50
|
+
/^#{python_script} \(#{gzip_compressed}/, res)
|
51
|
+
|
52
|
+
fm.close
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_buffer
|
56
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
57
|
+
res = fm.buffer("#!/bin/sh\n")
|
58
|
+
fm.close
|
59
|
+
assert_equal('POSIX shell script, ASCII text executable', res)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_check
|
63
|
+
return if Gem.win_platform?
|
64
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
65
|
+
res = silence_stderr { fm.check(path_to('perl')) }
|
66
|
+
fm.close
|
67
|
+
assert(res)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_check_compiled
|
71
|
+
return if MAGIC_VERSION <= 5.09
|
72
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
73
|
+
res = silence_stderr { fm.check(path_to('perl.mgc')) }
|
74
|
+
fm.close
|
75
|
+
assert(res)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_compile
|
79
|
+
assert(File.writable?('.'), "can't write to current directory")
|
80
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
81
|
+
res = fm.compile(path_to('perl'))
|
82
|
+
fm.close
|
83
|
+
assert(res)
|
84
|
+
File.unlink(path_to('perl.mgc', '.'))
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_block
|
88
|
+
block_fm = nil
|
89
|
+
res = FileMagic.open(FileMagic::MAGIC_NONE) { |fm|
|
90
|
+
block_fm = fm
|
91
|
+
fm.file(path_to('pyfile'))
|
92
|
+
}
|
93
|
+
assert_equal(match_version(
|
94
|
+
0 => 'a python script, ASCII text executable',
|
95
|
+
5.11 => 'Python script, ASCII text executable'
|
96
|
+
), res)
|
97
|
+
assert block_fm.closed?
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_flags_to_int
|
101
|
+
assert_raise(TypeError) { FileMagic.flags(0) }
|
102
|
+
assert_equal(0, FileMagic.flags([FileMagic::MAGIC_NONE]))
|
103
|
+
assert_equal(0, FileMagic.flags([:none]))
|
104
|
+
assert_equal(0, FileMagic.flags([]))
|
105
|
+
assert_equal(1072, FileMagic.flags([:mime, :continue]))
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_setflags
|
109
|
+
fm = FileMagic.new(FileMagic::MAGIC_NONE)
|
110
|
+
assert_equal([], fm.flags)
|
111
|
+
fm.flags = FileMagic::MAGIC_SYMLINK
|
112
|
+
assert_equal([:symlink], fm.flags)
|
113
|
+
fm.close
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_abbr
|
117
|
+
fm = FileMagic.new(:mime, :continue)
|
118
|
+
assert_equal([:mime_type, :continue, :mime_encoding], fm.flags)
|
119
|
+
fm.flags = :symlink
|
120
|
+
assert_equal([:symlink], fm.flags)
|
121
|
+
fm.close
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_close
|
125
|
+
fm = FileMagic.new
|
126
|
+
fm.close
|
127
|
+
assert fm.closed?
|
128
|
+
fm.close
|
129
|
+
assert fm.closed?
|
130
|
+
end
|
131
|
+
|
132
|
+
# tests adapted from mahoro:
|
133
|
+
|
134
|
+
def test_mahoro_file
|
135
|
+
fm = FileMagic.new
|
136
|
+
fm.flags = FileMagic::MAGIC_NONE
|
137
|
+
assert_equal(match_version(
|
138
|
+
0 => 'ASCII C program text',
|
139
|
+
5.11 => 'C source, ASCII text'
|
140
|
+
), fm.file(path_to('mahoro.c')))
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_mahoro_mime_file
|
144
|
+
fm = FileMagic.new
|
145
|
+
fm.flags = FileMagic::MAGIC_MIME
|
146
|
+
assert_equal('text/x-c; charset=us-ascii', fm.file(path_to('mahoro.c')))
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_mahoro_buffer
|
150
|
+
fm = FileMagic.new
|
151
|
+
fm.flags = FileMagic::MAGIC_NONE
|
152
|
+
assert_equal(match_version(
|
153
|
+
0 => 'ASCII C program text',
|
154
|
+
5.11 => 'C source, ASCII text'
|
155
|
+
), fm.buffer(File.read(path_to('mahoro.c'))))
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_mahoro_mime_buffer
|
159
|
+
fm = FileMagic.new
|
160
|
+
fm.flags = FileMagic::MAGIC_MIME
|
161
|
+
assert_equal('text/x-c; charset=us-ascii', fm.buffer(File.read(path_to('mahoro.c'))))
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_mahoro_valid
|
165
|
+
fm = FileMagic.new
|
166
|
+
assert(silence_stderr { fm.valid? }, 'Default database was not valid.')
|
167
|
+
end
|
168
|
+
|
169
|
+
# test abbreviating mime types
|
170
|
+
|
171
|
+
def test_abbrev_mime_type
|
172
|
+
fm = FileMagic.mime
|
173
|
+
|
174
|
+
refute fm.simplified?
|
175
|
+
assert_equal('text/plain; charset=us-ascii', fm.file(path_to('perl')))
|
176
|
+
|
177
|
+
fm.simplified = true
|
178
|
+
assert fm.simplified?
|
179
|
+
assert_equal('text/plain', fm.file(path_to('perl')))
|
180
|
+
assert_equal(match_version(
|
181
|
+
0 => 'application/vnd.ms-office',
|
182
|
+
5.11 => 'application/msword',
|
183
|
+
5.14 => 'application/vnd.ms-office'
|
184
|
+
), fm.file(path_to('excel-example.xls')))
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_singleton
|
188
|
+
fm1 = FileMagic.fm
|
189
|
+
assert_equal(fm1, FileMagic.fm)
|
190
|
+
|
191
|
+
refute fm1.simplified?
|
192
|
+
assert_equal('ASCII text', fm1.file(path_to('perl')))
|
193
|
+
|
194
|
+
fm2 = FileMagic.fm(:mime)
|
195
|
+
assert_equal(fm2, FileMagic.fm(:mime))
|
196
|
+
refute_equal(fm2, fm1)
|
197
|
+
|
198
|
+
refute fm2.simplified?
|
199
|
+
assert_equal('text/plain; charset=us-ascii', fm2.file(path_to('perl')))
|
200
|
+
|
201
|
+
fm3 = FileMagic.fm(:mime, simplified: true)
|
202
|
+
assert_equal(fm3, FileMagic.fm(:mime, simplified: true))
|
203
|
+
refute_equal(fm3, fm2)
|
204
|
+
refute_equal(fm3, fm1)
|
205
|
+
|
206
|
+
assert fm3.simplified?
|
207
|
+
assert_equal('text/plain', fm3.file(path_to('perl')))
|
208
|
+
end
|
209
|
+
|
210
|
+
# utility methods:
|
211
|
+
|
212
|
+
def path_to(file, dir = File.dirname(__FILE__))
|
213
|
+
File.join(dir, file)
|
214
|
+
end
|
215
|
+
|
216
|
+
def silence_stderr
|
217
|
+
require 'nuggets/io/redirect'
|
218
|
+
$stderr.redirect { yield }
|
219
|
+
rescue LoadError
|
220
|
+
yield
|
221
|
+
end
|
222
|
+
|
223
|
+
def match_version(versions)
|
224
|
+
versions.sort_by { |k,| -k }.find { |k,| k <= MAGIC_VERSION }.last
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
data/test/leaktest.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'filemagic'
|
3
|
+
|
4
|
+
warn "watch -n 1 'ps aux | grep [l]eaktest'"
|
5
|
+
|
6
|
+
def do_file(filename)
|
7
|
+
fm = FileMagic.new(0)
|
8
|
+
file = fm.file(filename)
|
9
|
+
fm.close
|
10
|
+
return file
|
11
|
+
end
|
12
|
+
|
13
|
+
loop do
|
14
|
+
puts do_file($0)
|
15
|
+
sleep 1
|
16
|
+
end
|
data/test/mahoro.c
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
/*
|
2
|
+
* This file is Public Domain.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <magic.h>
|
7
|
+
|
8
|
+
struct MagicCookie
|
9
|
+
{
|
10
|
+
magic_t cookie;
|
11
|
+
};
|
12
|
+
|
13
|
+
static VALUE cMahoro;
|
14
|
+
static VALUE eMahoroError;
|
15
|
+
|
16
|
+
static void
|
17
|
+
mahoro_free(ptr)
|
18
|
+
struct MagicCookie *ptr;
|
19
|
+
{
|
20
|
+
magic_close(ptr->cookie);
|
21
|
+
free(ptr);
|
22
|
+
}
|
23
|
+
|
24
|
+
static VALUE
|
25
|
+
mahoro_allocate(klass)
|
26
|
+
VALUE klass;
|
27
|
+
{
|
28
|
+
return Data_Wrap_Struct(klass, 0, mahoro_free, 0);
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE
|
32
|
+
mahoro_initialize(argc, argv, self)
|
33
|
+
int argc;
|
34
|
+
VALUE *argv, self;
|
35
|
+
{
|
36
|
+
int flags = MAGIC_NONE;
|
37
|
+
char *path = 0;
|
38
|
+
struct MagicCookie *ptr;
|
39
|
+
magic_t cookie;
|
40
|
+
VALUE vpath, vflags;
|
41
|
+
|
42
|
+
switch(rb_scan_args(argc, argv, "02", &vflags, &vpath)) {
|
43
|
+
case 2:
|
44
|
+
if(!NIL_P(vpath)) {
|
45
|
+
path = StringValuePtr(vpath);
|
46
|
+
}
|
47
|
+
/* fallthrough */
|
48
|
+
case 1:
|
49
|
+
flags = FIX2INT(vflags);
|
50
|
+
break;
|
51
|
+
}
|
52
|
+
|
53
|
+
if(!(cookie = magic_open(flags))) {
|
54
|
+
rb_raise(eMahoroError, "failed to initialize magic cookie");
|
55
|
+
}
|
56
|
+
|
57
|
+
if(magic_load(cookie, path)) {
|
58
|
+
rb_raise(eMahoroError, "failed to load database: %s",
|
59
|
+
magic_error(cookie));
|
60
|
+
}
|
61
|
+
|
62
|
+
ptr = ALLOC(struct MagicCookie);
|
63
|
+
ptr->cookie = cookie;
|
64
|
+
DATA_PTR(self) = ptr;
|
65
|
+
|
66
|
+
return self;
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE
|
70
|
+
mahoro_file(self, path)
|
71
|
+
VALUE self, path;
|
72
|
+
{
|
73
|
+
const char *msg;
|
74
|
+
magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
|
75
|
+
|
76
|
+
if(!(msg = magic_file(cookie, StringValuePtr(path)))) {
|
77
|
+
rb_raise(eMahoroError, "failed lookup: %s", magic_error(cookie));
|
78
|
+
}
|
79
|
+
|
80
|
+
return rb_str_new2(msg);
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
mahoro_buffer(self, input)
|
85
|
+
VALUE self, input;
|
86
|
+
{
|
87
|
+
const char *msg;
|
88
|
+
magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
|
89
|
+
|
90
|
+
if(!(msg = magic_buffer(cookie, StringValuePtr(input),
|
91
|
+
RSTRING(StringValue(input))->len))) {
|
92
|
+
rb_raise(eMahoroError, "failed lookup: %s", magic_error(cookie));
|
93
|
+
}
|
94
|
+
|
95
|
+
return rb_str_new2(msg);
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE
|
99
|
+
mahoro_set_flags(self, flags)
|
100
|
+
VALUE self, flags;
|
101
|
+
{
|
102
|
+
magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
|
103
|
+
|
104
|
+
return INT2FIX(magic_setflags(cookie, FIX2INT(flags)));
|
105
|
+
}
|
106
|
+
|
107
|
+
static VALUE
|
108
|
+
mahoro_check(argc, argv, self)
|
109
|
+
int argc;
|
110
|
+
VALUE *argv, self;
|
111
|
+
{
|
112
|
+
char *path = 0;
|
113
|
+
VALUE vpath;
|
114
|
+
magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
|
115
|
+
|
116
|
+
switch(rb_scan_args(argc, argv, "01", &vpath)) {
|
117
|
+
case 1:
|
118
|
+
if(!NIL_P(vpath)) {
|
119
|
+
path = StringValuePtr(vpath);
|
120
|
+
}
|
121
|
+
break;
|
122
|
+
}
|
123
|
+
|
124
|
+
if(!magic_check(cookie, path)) {
|
125
|
+
return Qtrue;
|
126
|
+
} else {
|
127
|
+
return Qfalse;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE
|
132
|
+
mahoro_compile(klass, path)
|
133
|
+
VALUE klass, path;
|
134
|
+
{
|
135
|
+
magic_t cookie = magic_open(MAGIC_NONE);
|
136
|
+
|
137
|
+
if(magic_compile(cookie, StringValuePtr(path))) {
|
138
|
+
rb_raise(eMahoroError, "failed compile: %s", magic_error(cookie));
|
139
|
+
}
|
140
|
+
|
141
|
+
magic_close(cookie);
|
142
|
+
|
143
|
+
return Qtrue;
|
144
|
+
}
|
145
|
+
|
146
|
+
static VALUE
|
147
|
+
mahoro_load(self, path)
|
148
|
+
VALUE self, path;
|
149
|
+
{
|
150
|
+
magic_t cookie = ((struct MagicCookie *) DATA_PTR(self))->cookie;
|
151
|
+
|
152
|
+
if(magic_load(cookie, StringValuePtr(path))) {
|
153
|
+
rb_raise(eMahoroError, "failed load: %s", magic_error(cookie));
|
154
|
+
}
|
155
|
+
|
156
|
+
return self;
|
157
|
+
}
|
158
|
+
|
159
|
+
void Init_mahoro(void)
|
160
|
+
{
|
161
|
+
cMahoro = rb_define_class("Mahoro", rb_cObject);
|
162
|
+
eMahoroError = rb_define_class_under(cMahoro, "Error", rb_eStandardError);
|
163
|
+
|
164
|
+
rb_const_set(cMahoro, rb_intern("NONE"), INT2FIX(MAGIC_NONE));
|
165
|
+
rb_const_set(cMahoro, rb_intern("DEBUG"), INT2FIX(MAGIC_DEBUG));
|
166
|
+
rb_const_set(cMahoro, rb_intern("SYMLINK"), INT2FIX(MAGIC_SYMLINK));
|
167
|
+
rb_const_set(cMahoro, rb_intern("COMPRESS"), INT2FIX(MAGIC_COMPRESS));
|
168
|
+
rb_const_set(cMahoro, rb_intern("DEVICES"), INT2FIX(MAGIC_DEVICES));
|
169
|
+
rb_const_set(cMahoro, rb_intern("MIME"), INT2FIX(MAGIC_MIME));
|
170
|
+
rb_const_set(cMahoro, rb_intern("CONTINUE"), INT2FIX(MAGIC_CONTINUE));
|
171
|
+
rb_const_set(cMahoro, rb_intern("CHECK"), INT2FIX(MAGIC_CHECK));
|
172
|
+
rb_const_set(cMahoro, rb_intern("PRESERVE_ATIME"),
|
173
|
+
INT2FIX(MAGIC_PRESERVE_ATIME));
|
174
|
+
rb_const_set(cMahoro, rb_intern("RAW"), INT2FIX(MAGIC_RAW));
|
175
|
+
rb_const_set(cMahoro, rb_intern("ERROR"), INT2FIX(MAGIC_ERROR));
|
176
|
+
|
177
|
+
rb_define_alloc_func(cMahoro, mahoro_allocate);
|
178
|
+
rb_define_method(cMahoro, "initialize", mahoro_initialize, -1);
|
179
|
+
rb_define_method(cMahoro, "file", mahoro_file, 1);
|
180
|
+
rb_define_method(cMahoro, "buffer", mahoro_buffer, 1);
|
181
|
+
rb_define_method(cMahoro, "flags=", mahoro_set_flags, 1);
|
182
|
+
rb_define_method(cMahoro, "valid?", mahoro_check, -1);
|
183
|
+
rb_define_singleton_method(cMahoro, "compile", mahoro_compile, 1);
|
184
|
+
rb_define_method(cMahoro, "load", mahoro_load, 1);
|
185
|
+
}
|
186
|
+
|
187
|
+
/* arch-tag: mahoro */
|