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