lib/bsd/sys/admin.rb in sys-admin-1.6.2 vs lib/bsd/sys/admin.rb in sys-admin-1.6.3

- old
+ new

@@ -1,14 +1,18 @@ require 'sys/admin/custom' require 'sys/admin/common' +require 'rbconfig' # The BSD specific code. module Sys class Admin private + # :no-doc: + BUF_MAX = 65536 # Max buffer for retry + # I'm making some aliases here to prevent potential conflicts attach_function :open_c, :open, [:string, :int], :int attach_function :pread_c, :pread, [:int, :pointer, :size_t, :off_t], :size_t attach_function :close_c, :close, [:int], :int @@ -22,22 +26,28 @@ private_class_method :getgrgid_r private_class_method :open_c, :pread_c, :close_c # struct passwd from /usr/include/pwd.h class PasswdStruct < FFI::Struct - layout( + fields = [ :pw_name, :string, :pw_passwd, :string, - :pw_uid, :uint, - :pw_gid, :uint, - :pw_change, :ulong, + :pw_uid, :uid_t, + :pw_gid, :gid_t, + :pw_change, :time_t, :pw_class, :string, :pw_gecos, :string, :pw_dir, :string, :pw_shell, :string, - :pw_expire, :ulong - ) + :pw_expire, :time_t + ] + + if RbConfig::CONFIG['host_os'] =~ /freebsd/i + fields.push(:pw_fields, :int) + end + + layout(*fields) end # struct group from /usr/include/grp.h class GroupStruct < FFI::Struct layout( @@ -111,27 +121,34 @@ # # Sys::Admin.get_group('admin') # Sys::Admin.get_group(101) # def self.get_group(gid) - buf = FFI::MemoryPointer.new(:char, 1024) + size = 1024 + buf = FFI::MemoryPointer.new(:char, size) pbuf = FFI::MemoryPointer.new(PasswdStruct) temp = GroupStruct.new - if gid.is_a?(String) - if getgrnam_r(gid, temp, buf, buf.size, pbuf) != 0 - raise Error, "getgrnam_r function failed: " + strerror(FFI.errno) + begin + if gid.is_a?(String) + val = getgrnam_r(gid, temp, buf, buf.size, pbuf) + fun = 'getgrnam_r' + else + val = getgrgid_r(gid, temp, buf, buf.size, pbuf) + fun = 'getgrgid_r' end - else - if getgrgid_r(gid, temp, buf, buf.size, pbuf) != 0 - raise Error, "getgrgid_r function failed: " + strerror(FFI.errno) - end + raise SystemCallError.new(fun, val) if val != 0 + rescue Errno::ERANGE + size += 1024 + raise if size > BUF_MAX + buf = FFI::MemoryPointer.new(:char, size) + retry end ptr = pbuf.read_pointer if ptr.null? - raise Error, "no group found for #{gid}" + raise Error, "no group found for '#{gid}'" end grp = GroupStruct.new(ptr) get_group_from_struct(grp) end