glongman-otv-ffiruby-filemagic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,116 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+ class FFIFileMagicError < StandardError; end
4
+ class FFIFileMagic
5
+ # constants (see magic.h)
6
+ MAGIC_NONE =0x000000 # No flags
7
+ MAGIC_DEBUG =0x000001 # Turn on debugging
8
+ MAGIC_SYMLINK =0x000002 # Follow symlinks
9
+ MAGIC_COMPRESS =0x000004 # Check inside compressed files
10
+ MAGIC_DEVICES =0x000008 # Look at the contents of devices
11
+ MAGIC_MIME_TYPE =0x000010 # Return only the MIME type
12
+ MAGIC_CONTINUE =0x000020 # Return all matches
13
+ MAGIC_CHECK =0x000040 # Print warnings to stderr
14
+ MAGIC_PRESERVE_ATIME =0x000080 # Restore access time on exit
15
+ MAGIC_RAW =0x000100 # Don't translate unprint chars
16
+ MAGIC_ERROR =0x000200 # Handle ENOENT etc as real errors
17
+ MAGIC_MIME_ENCODING =0x000400 # Return only the MIME encoding
18
+ MAGIC_MIME =(FFIFileMagic::MAGIC_MIME_TYPE|FFIFileMagic::MAGIC_MIME_ENCODING)
19
+ MAGIC_NO_CHECK_COMPRESS =0x001000 # Don't check for compressed files
20
+ MAGIC_NO_CHECK_TAR =0x002000 # Don't check for tar files
21
+ MAGIC_NO_CHECK_SOFT =0x004000 # Don't check magic entries
22
+ MAGIC_NO_CHECK_APPTYPE =0x008000 # Don't check application type
23
+ MAGIC_NO_CHECK_ELF =0x010000 # Don't check for elf details
24
+ MAGIC_NO_CHECK_ASCII =0x020000 # Don't check for ascii files
25
+ MAGIC_NO_CHECK_TOKENS =0x100000 # Don't check ascii/tokens
26
+
27
+ def initialize(flags)
28
+ @cookie = Native::magic_open(flags)
29
+ raise "out of memory" unless @cookie
30
+ raise FFIFileMagicError, Native::magic_error(@cookie) if Native::magic_load(@cookie, nil) == -1
31
+ end
32
+
33
+ def check_cookie
34
+ raise "invalid state: closed" unless @cookie
35
+ end
36
+
37
+ # returns a textual description of the contents of the filename argument
38
+ def file(filename)
39
+ check_cookie
40
+ raise FFIFileMagicError, Native::magic_error(@cookie) if (result = Native::magic_file(@cookie, filename)) == nil
41
+ result
42
+ end
43
+
44
+ # returns a textual description of the contents of the string argument
45
+ def buffer(string)
46
+ check_cookie
47
+ raise FFIFileMagicError, Native::magic_error(@cookie) if (result = Native::magic_buffer(@cookie, string, string.length)) == nil
48
+ result
49
+ end
50
+
51
+ # checks the validity of entries in the colon separated database files passed in as filename
52
+ def check(filename)
53
+ check_cookie
54
+ Native::magic_check(@cookie, filename);
55
+ end
56
+ # compile the the colon separated list of database files passed in as filename
57
+ def compile(filename)
58
+ check_cookie
59
+ Native::magic_compile(@cookie, filename);
60
+ end
61
+
62
+ # closes the magic database and frees any memory allocated.
63
+ # if memory is a concern, use this.
64
+ def close
65
+ check_cookie
66
+ Native::magic_close(@cookie);
67
+ @cookie = nil
68
+ end
69
+
70
+ module Native
71
+ extend FFI::Library
72
+
73
+ begin
74
+ ffi_lib 'magic'
75
+ rescue LoadError
76
+ libsuffix = %x(uname -a) =~ /Darwin/ ? '.dylib' : '.so'
77
+ ffi_lib "/opt/local/lib/libmagic" + libsuffix
78
+ end
79
+
80
+ #magic_t is a pointer (I think)
81
+ #magic_t magic_open(int);
82
+ attach_function :magic_open, [:int], :pointer
83
+
84
+ #void magic_close(magic_t);
85
+ attach_function :magic_close, [:pointer], :void
86
+
87
+ # const char *magic_file(magic_t, const char *);
88
+ attach_function :magic_file, [:pointer, :string], :string
89
+
90
+ # const char *magic_descriptor(magic_t, int);
91
+ attach_function :magic_descriptor, [:pointer, :int], :string
92
+
93
+ # const char *magic_buffer(magic_t, const void *, size_t);
94
+ attach_function :magic_buffer, [:pointer, :pointer, :int], :string
95
+
96
+ # const char *magic_error(magic_t);
97
+ attach_function :magic_error, [:pointer], :string
98
+
99
+ # int magic_setflags(magic_t, int);
100
+ attach_function :magic_setflags, [:pointer, :int], :int
101
+
102
+ # int magic_load(magic_t, const char *);
103
+ attach_function :magic_load, [:pointer, :string], :int
104
+
105
+ # int magic_compile(magic_t, const char *);
106
+ attach_function :magic_compile, [:pointer, :string], :int
107
+
108
+ # int magic_check(magic_t, const char *);
109
+ attach_function :magic_check, [:pointer, :string], :int
110
+
111
+ # int magic_errno(magic_t);
112
+ attach_function :magic_errno, [:pointer], :int
113
+
114
+ end
115
+ end
116
+
@@ -0,0 +1,66 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ require 'ruby-debug'
3
+ class TestFFIFileMagic < Test::Unit::TestCase
4
+ BASE = File.expand_path(File.dirname(__FILE__)) + "/"
5
+ FILE = BASE + "pyfile"
6
+ LINK = BASE + 'pylink'
7
+ COMPRESSED = BASE + 'pyfile-compressed.gz'
8
+ PERL = BASE + "perl"
9
+ DB = File.expand_path(BASE + '../perl.mgc')
10
+ def test_file
11
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_NONE)
12
+ res = fm.file FILE
13
+ assert_equal("a python script text executable", res)
14
+ end
15
+
16
+ def test_symlink
17
+ File.symlink FILE, LINK
18
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_NONE)
19
+ res = fm.file LINK
20
+ assert_match(/^symbolic link to `.*pyfile'$/, res)
21
+ fm.close
22
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_SYMLINK)
23
+ res = fm.file LINK
24
+ assert_equal("a python script text executable", res)
25
+ fm.close
26
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_SYMLINK | FFIFileMagic::MAGIC_MIME)
27
+ res = fm.file LINK
28
+ assert_equal("text/plain charset=us-ascii", res)
29
+ fm.close
30
+ ensure
31
+ File.unlink LINK
32
+ end
33
+
34
+ def test_compressed
35
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_COMPRESS)
36
+ res = fm.file COMPRESSED
37
+ assert_match(/^a python script text executable/, res)
38
+ fm.close
39
+ end
40
+
41
+ def test_buffer
42
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_NONE)
43
+ res = fm.buffer("#!/bin/sh\n")
44
+ fm.close
45
+ assert_equal("POSIX shell script text executable", res)
46
+ end
47
+
48
+ def test_check
49
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_NONE)
50
+ res = fm.check PERL
51
+ fm.close
52
+ assert_equal(0, res)
53
+ end
54
+
55
+ def test_compile
56
+ fm = FFIFileMagic.new(FFIFileMagic::MAGIC_NONE)
57
+ res = fm.compile PERL
58
+ fm.close
59
+ assert_equal(0, res)
60
+ File.unlink DB
61
+ end
62
+
63
+ def file(name)
64
+ File.expand_path(File.dirname(__FILE__)) + "/" + name
65
+ end
66
+ end
data/test/leaktest.rb ADDED
@@ -0,0 +1,15 @@
1
+ require '../filemagic'
2
+
3
+ # watch -n 1 'ps aux | grep leaktest'
4
+
5
+ def do_file(filename)
6
+ fm = FileMagic.new(0)
7
+ file = fm.file(filename)
8
+ fm.close
9
+ return file
10
+ end
11
+
12
+ loop do
13
+ puts do_file($0)
14
+ sleep 1
15
+ end
data/test/perl ADDED
@@ -0,0 +1,19 @@
1
+
2
+ #------------------------------------------------------------------------------
3
+ # perl: file(1) magic for Larry Wall's perl language.
4
+ #
5
+ # The ``eval'' line recognizes an outrageously clever hack for USG systems.
6
+ # Keith Waclena <keith@cerberus.uchicago.edu>
7
+ # Send additions to <perl5-porters@perl.org>
8
+ 0 string/b #!\ /bin/perl perl script text executable
9
+ 0 string eval\ "exec\ /bin/perl perl script text
10
+ 0 string/b #!\ /usr/bin/perl perl script text executable
11
+ 0 string eval\ "exec\ /usr/bin/perl perl script text
12
+ 0 string/b #!\ /usr/local/bin/perl perl script text
13
+ 0 string eval\ "exec\ /usr/local/bin/perl perl script text executable
14
+ 0 string eval\ '(exit\ $?0)'\ &&\ eval\ 'exec perl script text
15
+
16
+ # a couple more, by me
17
+ # XXX: christos matches
18
+ #0 regex package Perl5 module source text (via regex)
19
+ 0 string package Perl5 module source text
data/test/pyfile ADDED
@@ -0,0 +1 @@
1
+ """
Binary file
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/ffi_file_magic')
5
+
6
+ class Test::Unit::TestCase
7
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glongman-otv-ffiruby-filemagic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Geoff Longman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-02 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ffi
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description: new implementation of the ancient ruby-filemagic gem. Uses FFI to talk to native library
25
+ email: glongman@overlay.tv
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - VERSION.yml
34
+ - lib/ffi_file_magic.rb
35
+ - test/ffiruby_filemagic_test.rb
36
+ - test/leaktest.rb
37
+ - test/perl
38
+ - test/pyfile
39
+ - test/pyfile-compressed.gz
40
+ - test/test_helper.rb
41
+ has_rdoc: true
42
+ homepage: http://github.com/glongman-otv/ffiruby-filemagic
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --inline-source
46
+ - --charset=UTF-8
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.2.0
65
+ signing_key:
66
+ specification_version: 2
67
+ summary: new implementation of the ancient ruby-filemagic gem. Uses FFI to talk to native library
68
+ test_files: []
69
+