Skip to content

Instantly share code, notes, and snippets.

@slyphon
Created October 3, 2009 02:07
Show Gist options
  • Save slyphon/200346 to your computer and use it in GitHub Desktop.
Save slyphon/200346 to your computer and use it in GitHub Desktop.
require 'rubygems'
# gem 'ffi', '= 0.3.5'
require 'ffi'
require 'fileutils'
if defined?(JRUBY_VERSION)
jsys = java.lang.System
$stderr.puts "#{jsys.get_property('java.vm.name')} #{jsys.get_property('java.version')}"
end
module CurlFfi
module Easy
extend FFI::Library
class CurlFfiError < StandardError
end
COTYPE_LONG = 0
COTYPE_OBJECTPOINT = 10_000
COTYPE_FUNCTIONPOINT = 20_000
COTYPE_OFF_T = 30_000
# constants defined in curl.h
CURL_GLOBAL_SSL = (1 << 0)
CURL_GLOBAL_WIN32 = (1 << 1)
CURL_GLOBAL_ALL = (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
CURL_GLOBAL_NOTHING = 0
CURL_GLOBAL_DEFAULT = CURL_GLOBAL_ALL
# options
CURLOPT_FILE = COTYPE_OBJECTPOINT + 1
CURLOPT_URL = COTYPE_OBJECTPOINT + 2
CURLOPT_ERRORBUFFER = COTYPE_OBJECTPOINT + 10
CURLOPT_WRITEFUNCTION = COTYPE_FUNCTIONPOINT + 11
# status
CURLE_OK = 0
ffi_lib "curl"
attach_function :_global_init, :curl_global_init, [:long], :int
attach_function :_init, :curl_easy_init, [], :pointer
attach_function :_cleanup, :curl_easy_cleanup, [:pointer], :void
attach_function :_setopt, :curl_easy_setopt, [:pointer, :int, :pointer], :int
attach_function :_setoptstr, :curl_easy_setopt, [:pointer, :int, :string], :int
attach_function :_setoptva, :curl_easy_setopt, [:pointer, :int, :varargs], :int
attach_function :_perform, :curl_easy_perform, [:pointer], :int
attach_function :_strerror, :curl_easy_strerror, [:int], :string
@@global_init_done = false unless defined?(@@global_init_done)
@@mutex = Mutex.new unless defined?(@@mutex)
attr_reader :url
def self.global_init!
@@mutex.synchronize do
return if @@global_init_done
@@global_init_done = true
_global_init(CURL_GLOBAL_DEFAULT)
end
end
class StdIO
extend FFI::Library
ffi_lib 'c'
attach_function :_fopen, :fopen, [:string, :string], :pointer
attach_function :_fdopen, :fdopen, [:int, :string], :pointer
attach_function :_fclose, :fclose, [:pointer], :int
attach_function :_fflush, :fflush, [:pointer], :int
attach_function :_strerror, :strerror, [:int], :string
attach_function :_printf, :printf, [:varargs], :int
class << self
def fopen(path, mode)
_fopen(path, mode) or raise_errno!
end
def fdopen(int, str)
_fdopen(int, str) or raise_errno!
end
def fclose(ptr)
raise_errno! unless _fclose(ptr) == 0
end
def fflush(ptr)
raise_errno! unless _fflush(ptr) == 0
end
private
def raise_errno!
raise SystemCallError.new(nil, FFI.errno)
end
end
end
class << self
def download(url, path)
fp = nil
handle = self._init
$stderr.puts "printing url from stdlib printf"
StdIO._printf(:string, url)
self._setoptstr(handle, CURLOPT_URL, url)
self._setopt(handle, CURLOPT_WRITEFUNCTION, nil)
fpointer = StdIO.fopen(path, 'w')
p fpointer
self._setopt(handle, CURLOPT_FILE, fpointer)
if (code = self._perform(handle)) > CURLE_OK
raise CurlFfiError, self._strerror(code)
end
StdIO.fflush(fpointer)
true
rescue Exception => e
FileUtils.rm_f(path) rescue nil
raise e
ensure
StdIO.fclose(fpointer) if fpointer
self._cleanup(handle) if handle
end
private
def raise_curl_errno!
raise CurlFfiError, self._strerror
end
end
end
end
def main
if ARGV.empty?
$stderr.puts "Usage: #{File.basename($0)} http://example.com/ /tmp/blah.out"
exit 1
end
CurlFfi::Easy.global_init!
url = ARGV.first
outpath = ARGV[1]
CurlFfi::Easy.download(url, outpath)
end
main if __FILE__ == $0
[20091003-02.14.14]$ jruby curlffi.rb http://www.google.com/ /tmp/blah.html
Java HotSpot(TM) 64-Bit Server VM 1.6.0_07
printing url from stdlib printf
#<Pointer address=0x7fff700d0440>
curlffi.rb:119:in `download': couldn't resolve host name (CurlFfi::Easy::CurlFfiError)
from curlffi.rb:152:in `main'
from curlffi.rb:155
http://www.google.com/
[20091003-02.15.30]$ uname -a
Darwin hackett 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1/RELEASE_I386 i386
slyphon@hackett:~
[20091003-02.15.33]$ jruby --version
jruby 1.3.1 (ruby 1.8.6p287) (2009-09-21 6586) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_07) [x86_64-java]
slyphon@hackett:~
[20091003-02.16.15]$ $JAVA_HOME/bin/java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0_07-b06-57, mixed mode)
slyphon@hackett:~
[20091003-02.16.28]$ curl --version
curl 7.19.6 (i386-apple-darwin9.6.0) libcurl/7.19.6 OpenSSL/0.9.8k zlib/1.2.3
Protocols: tftp ftp telnet dict http file https ftps
Features: Largefile NTLM SSL libz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment