/lib/ffi/libc/libc.rb

https://github.com/postmodern/ffi-libc · Ruby · 220 lines · 142 code · 36 blank · 42 comment · 5 complexity · 2f735d5524f170f65ac77a36d9d88d8a MD5 · raw file

  1. require 'ffi/libc/types'
  2. require 'ffi/libc/timeval'
  3. require 'ffi/libc/timezone'
  4. require 'ffi/libc/ifaddrs'
  5. require 'ffi/libc/rusage'
  6. require 'ffi'
  7. module FFI
  8. module LibC
  9. extend FFI::Library
  10. ffi_lib FFI::Library::LIBC
  11. # The NULL constant
  12. NULL = nil
  13. # errno.h
  14. begin
  15. attach_variable :sys_errlist, :pointer
  16. attach_variable :sys_nerr, :int
  17. rescue FFI::NotFoundError
  18. end
  19. attach_variable :errno, :int
  20. def self.raise_error(error=self.errno)
  21. raise(strerror(error))
  22. end
  23. # unistd.h
  24. attach_function :brk, [:pointer], :int
  25. attach_function :sbrk, [:pointer], :pointer
  26. attach_function :getpid, [], :pid_t
  27. attach_function :getppid, [], :pid_t
  28. attach_function :getuid, [], :uid_t
  29. attach_function :geteuid, [], :uid_t
  30. attach_function :getgid, [], :gid_t
  31. attach_function :getegid, [], :gid_t
  32. attach_function :alarm, [:uint], :uint
  33. # stdlib.h
  34. attach_function :calloc, [:size_t, :size_t], :pointer
  35. attach_function :malloc, [:size_t], :pointer
  36. attach_function :free, [:pointer], :void
  37. attach_function :realloc, [:pointer, :size_t], :pointer
  38. attach_function :getenv, [:string], :string
  39. attach_function :putenv, [:string], :int
  40. attach_function :unsetenv, [:string], :int
  41. begin
  42. attach_function :clearenv, [], :int
  43. rescue FFI::NotFoundError
  44. # clearenv is not available on OSX
  45. end
  46. # time.h
  47. attach_function :clock, [], :clock_t
  48. attach_function :time, [:pointer], :time_t
  49. # sys/time.h
  50. attach_function :gettimeofday, [:pointer, :pointer], :int
  51. attach_function :settimeofday, [:pointer, :pointer], :int
  52. # sys/mman.h
  53. attach_function :mmap, [:pointer, :size_t, :int, :int, :int, :off_t], :pointer
  54. attach_function :munmap, [:pointer, :size_t], :int
  55. # string.h
  56. attach_function :bzero, [:pointer, :size_t], :void
  57. attach_function :memset, [:pointer, :int, :size_t], :pointer
  58. attach_function :memcpy, [:buffer_out, :buffer_in, :size_t], :pointer
  59. attach_function :memcmp, [:buffer_in, :buffer_in, :size_t], :int
  60. attach_function :memchr, [:buffer_in, :int, :size_t], :pointer
  61. begin
  62. attach_function :memrchr, [:buffer_in, :int, :size_t], :pointer
  63. rescue FFI::NotFoundError
  64. # memrchr is not available on OSX
  65. end
  66. attach_function :strcpy, [:buffer_out, :string], :pointer
  67. attach_function :strncpy, [:buffer_out, :string, :size_t], :pointer
  68. attach_function :strcmp, [:buffer_in, :buffer_in], :int
  69. attach_function :strncmp, [:buffer_in, :buffer_in, :size_t], :int
  70. attach_function :strlen, [:buffer_in], :size_t
  71. attach_function :index, [:buffer_in, :int], :pointer
  72. attach_function :rindex, [:buffer_in, :int], :pointer
  73. attach_function :strchr, [:buffer_in, :int], :pointer
  74. attach_function :strrchr, [:buffer_in, :int], :pointer
  75. attach_function :strstr, [:buffer_in, :string], :pointer
  76. attach_function :strerror, [:int], :string
  77. begin
  78. attach_variable :stdin, :pointer
  79. attach_variable :stdout, :pointer
  80. attach_variable :stderr, :pointer
  81. rescue FFI::NotFoundError
  82. # stdin, stdout, stderr are not available on OSX
  83. end
  84. attach_function :fopen, [:string, :string], :FILE
  85. attach_function :fdopen, [:int, :string], :FILE
  86. attach_function :freopen, [:string, :string, :FILE], :FILE
  87. attach_function :fseek, [:FILE, :long, :int], :int
  88. attach_function :ftell, [:FILE], :long
  89. attach_function :rewind, [:FILE], :void
  90. attach_function :fread, [:buffer_out, :size_t, :size_t, :FILE], :size_t
  91. attach_function :fwrite, [:buffer_in, :size_t, :size_t, :FILE], :size_t
  92. attach_function :fgetc, [:FILE], :int
  93. attach_function :fgets, [:buffer_out, :int, :FILE], :pointer
  94. attach_function :fputc, [:int, :FILE], :int
  95. attach_function :fputs, [:buffer_in, :FILE], :int
  96. attach_function :fflush, [:FILE], :int
  97. attach_function :fclose, [:FILE], :int
  98. attach_function :clearerr, [:FILE], :void
  99. attach_function :feof, [:FILE], :int
  100. attach_function :ferror, [:FILE], :int
  101. attach_function :fileno, [:FILE], :int
  102. attach_function :perror, [:string], :void
  103. attach_function :getc, [:FILE], :int
  104. attach_function :getchar, [], :int
  105. attach_function :gets, [:buffer_out], :int
  106. attach_function :ungetc, [:int, :pointer], :int
  107. attach_function :putc, [:int, :FILE], :int
  108. attach_function :putchar, [:int], :int
  109. attach_function :puts, [:string], :int
  110. # netdb.h
  111. attach_function :getnameinfo, [
  112. :pointer,
  113. :socklen_t, :pointer,
  114. :socklen_t, :pointer,
  115. :socklen_t, :int
  116. ], :int
  117. NI_MAXHOST = 1024
  118. NI_MAXSERV = 32
  119. NI_NUMERICHOST = 1 # Don't try to look up hostname.
  120. NI_NUMERICSERV = 2 # Don't convert port number to name.
  121. NI_NOFQDN = 4 # Only return nodename portion.
  122. NI_NAMEREQD = 8 # Don't return numeric addresses.
  123. NI_DGRAM = 16 # Look up UDP service rather than TCP.
  124. # ifaddrs.h
  125. attach_function :getifaddrs, [:pointer], :int
  126. attach_function :freeifaddrs, [:pointer], :void
  127. #
  128. # Enumerates over the Interface Addresses.
  129. #
  130. # @yield [ifaddr]
  131. # The given block will be passed each Interface Address.
  132. #
  133. # @yieldparam [Ifaddrs] ifaddr
  134. # An Interface Address.
  135. #
  136. # @return [Enumerator]
  137. # If no block is given, an enumerator will be returned.
  138. #
  139. # @since 0.1.0
  140. #
  141. def self.each_ifaddr
  142. return enum_for(__method__) unless block_given?
  143. ptr = MemoryPointer.new(:pointer)
  144. if getifaddrs(ptr) == -1
  145. raise_error
  146. end
  147. if (ifaddrs = ptr.get_pointer(0)).null?
  148. return
  149. end
  150. ifaddr = Ifaddrs.new(ifaddrs)
  151. while ifaddr
  152. yield ifaddr
  153. ifaddr = ifaddr.next
  154. end
  155. freeifaddrs(ifaddrs)
  156. end
  157. # bits/resource.h (Linux) / sys/resource.h (Darwin)
  158. RUSAGE_SELF = 0
  159. RUSAGE_CHILDREN = -1
  160. RUSAGE_THREAD = 1 # Linux/glibc only
  161. attach_function :getrusage, [:int, :pointer], :int
  162. #
  163. # Gets the RUsage for the user.
  164. #
  165. # @param [RUSAGE_SELF, RUSAGE_CHILDREN, RUSAGE_THREAD] who
  166. # Whome to get RUsage statistics for.
  167. #
  168. # @return [RUsage]
  169. # The RUsage statistics.
  170. #
  171. # @raise [RuntimeError]
  172. # An error has occurred.
  173. #
  174. # @since 0.1.0
  175. #
  176. def self.rusage(who=RUSAGE_SELF)
  177. rusage = RUsage.new
  178. unless (ret = getrusage(who,rusage)) == 0
  179. raise_error(ret)
  180. end
  181. return rusage
  182. end
  183. end
  184. end