aperture/src/libmagic.rb
snow flurry f25803aaa5 multiple syntax fixes
I never said I was *good* at ruby...
2021-03-24 21:47:17 -07:00

118 lines
3.8 KiB
Ruby

require 'ffi'
module LibMagic
extend FFI::Library
ffi_lib 'magic'
## constants
MAGIC_NONE = 0x0
MAGIC_DEBUG = 0x1
MAGIC_SYMLINK = 0x2
MAGIC_COMPRESS = 0x4
MAGIC_DEVICES = 0x8
MAGIC_MIME_TYPE = 0x10
MAGIC_CONTINUE = 0x20
MAGIC_CHECK = 0x40
MAGIC_PRESERVE_ATIME = 0x80
MAGIC_RAW = 0x100
MAGIC_ERROR = 0x200
MAGIC_MIME_ENCODING = 0x400
MAGIC_MIME = (MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING)
MAGIC_APPLE = 0x800
MAGIC_EXTENSION = 0x1000000
MAGIC_COMPRESS_TRANSP = 0x2000000
# error used for handling libmagic errors
class MagicError < StandardError
def initialize(msg="Unknown error occurred", errno=0)
@errno = errno
super(msg)
end
end
class Magic
# initialize libmagic
def initialize(db_path = nil, flags = LibMagic::MAGIC_MIME_TYPE)
# nullptr for default db path
# dbptr = FFI::Pointer.new 0x0
dbptr = nil
@magic_inst = LibMagic::ffi_magic_open(flags)
if @magic_inst.null?
raise "magic_open() failed"
end
# now that we have our cookie, clear it on exit
at_exit do
self.close
end
# load magic database
if !db_path.nil?
dbptr = db_path
end
res = LibMagic::ffi_magic_load(@magic_inst, dbptr)
if res != 0
self.throw_error
end
end
# Gets MIME type for a given stream
def get_mime_type(stream)
res = nil
if stream.fileno.nil? # magic_buffer
buf = stream.string
buflen = buf.bytesize
res, ptr = LibMagic::ffi_magic_buffer(@magic_inst, buf, buflen)
else # magic_descriptor
res, ptr = LibMagic::ffi_magic_descriptor(@magic_inst, stream.fileno)
end
if res.nil? || res.empty?
self.throw_error
end
return res
end
def close()
unless @magic_inst.nil?
LibMagic::ffi_magic_close(@magic_inst)
@magic_inst = nil
end
end
private
# convenience method for throwing MagicErrors
def throw_error()
if @magic_inst.null?
raise LibMagic::MagicError.new
else
errptr = LibMagic::ffi_magic_error(@magic_inst)
errno = LibMagic::ffi_magic_errno(@magic_inst)
errstr, errfree = FFI::StrPtrConverter.from_native(errptr, nil)
raise LibMagic::MagicError.new(errstr, errno)
end
end
end
## ffi
# i/o open/close
attach_function :ffi_magic_open, :magic_open, [:int], :pointer
attach_function :ffi_magic_close, :magic_close, [:pointer], :void
# error info (a la GetLastError/win32)
attach_function :ffi_magic_error, :magic_error, [:pointer], :strptr
attach_function :ffi_magic_errno, :magic_errno, [:pointer], :int
# libmagic flags
attach_function :ffi_magic_getflags, :magic_getflags, [:pointer], :int
attach_function :ffi_magic_setflags, :magic_setflags, [:pointer, :int], :int
# load the libmagic db -- MUST BE DONE BEFORE GETTING MAGIC INFO
attach_function :ffi_magic_load, :magic_load, [:pointer, :string], :int
# get magic info
attach_function :ffi_magic_file, :magic_file, [:pointer, :string], :strptr
attach_function :ffi_magic_buffer, :magic_buffer, [:pointer, :pointer, :size_t], :strptr
attach_function :ffi_magic_descriptor, :magic_descriptor, [:pointer, :int], :strptr
end