Large uid's with Etc.getpwnam

I beleve there is a bug in Etc.getpwnam. On our OS X server running 10.4 with ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0] we use AD for user management.
The two id's the one that is my real id i got from ls -ln and the one from getpwnam differ only in the sign bit, so it looks like ruby is treating it as a 1's compliment number when it is an unsigned int. i could change if you take -566183520 & 0x7FFFFFFF in ruby it will return the proper number 1581300128. The same happens for all users with larger id's in our AD system.

irb(main):016:0> Etc.getpwuid(1581300128)
=> #<struct Struct::Passwd name="mcgoverp", passwd="********", uid=-566183520, gid=513, gecos="Ryan McGovern", dir="/Network/Servers/ucfilespace.uc.edu/Home/m/mcgoverp", shell="/usr/local/profile", change=0, uclass="", expire=0>

irb(main):017:0> uinf=Etc.getpwnam("mcgoverp")
=> #<struct Struct::Passwd name="mcgoverp", passwd="********", uid=-566183520, gid=513, gecos="Ryan McGovern", dir="/Network/Servers/ucfilespace.uc.edu/Home/m/mcgoverp", shell="/usr/local/profile", change=0, uclass="", expire=0>

irb(main):019:0> Etc.getpwuid(-566183520)
ArgumentError: can't find user for -566183520
        from (irb):19:in `getpwuid'
        from (irb):19

irb(main):005:0> Etc.getpwnam("monkir")
=> #<struct Struct::Passwd name="monkir", passwd="********", uid=-476125468, gid=513, gecos="Ian Monk", dir="/Network/Servers/ucfilespace.uc.edu/Home/m/monkir", shell="/bin/bash", change=0, uclass="", expire=0>
irb(main):006:0> Etc.getpwnam("monkir").uid & 0x7FFFFFFF
=> 1671358180
irb(main):007:0> Etc.getpwuid(1671358180)
=> #<struct Struct::Passwd name="monkir", passwd="********", uid=-476125468, gid=513, gecos="Ian Monk", dir="/Network/Servers/ucfilespace.uc.edu/Home/m/monkir", shell="/bin/bash", change=0, uclass="", expire=0>

···

from :0

Hi,

At Tue, 27 Jun 2006 00:06:18 +0900,
Ryan McGovern wrote in [ruby-talk:199102]:

I beleve there is a bug in Etc.getpwnam. On our OS X server
running 10.4 with ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0]
we use AD for user management.

Does this help?

* ext/etc/etc.c (setup_passwd, setup_group): allow bignum uid, gid and
  so on. [ruby-talk:199102]

Index: ext/etc/etc.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/ext/etc/etc.c,v
retrieving revision 1.22
diff -p -u -2 -r1.22 etc.c
--- ext/etc/etc.c 20 Jun 2006 18:02:14 -0000 1.22
+++ ext/etc/etc.c 26 Jun 2006 16:53:48 -0000
@@ -77,6 +77,6 @@ setup_passwd(struct passwd *pwd)
        safe_setup_str(pwd->pw_passwd),
#endif
- INT2FIX(pwd->pw_uid),
- INT2FIX(pwd->pw_gid),
+ PW_UID2VAL(pwd->pw_uid),
+ PW_GID2VAL(pwd->pw_gid),
#ifdef HAVE_ST_PW_GECOS
        safe_setup_str(pwd->pw_gecos),
@@ -85,8 +85,8 @@ setup_passwd(struct passwd *pwd)
        safe_setup_str(pwd->pw_shell),
#ifdef HAVE_ST_PW_CHANGE
- INT2FIX(pwd->pw_change),
+ INT2NUM(pwd->pw_change),
#endif
#ifdef HAVE_ST_PW_QUOTA
- INT2FIX(pwd->pw_quota),
+ INT2NUM(pwd->pw_quota),
#endif
#ifdef HAVE_ST_PW_AGE
@@ -100,5 +100,5 @@ setup_passwd(struct passwd *pwd)
#endif
#ifdef HAVE_ST_PW_EXPIRE
- INT2FIX(pwd->pw_expire),
+ INT2NUM(pwd->pw_expire),
#endif
        0 /*dummy*/
@@ -302,5 +302,5 @@ setup_group(struct group *grp)
        safe_setup_str(grp->gr_passwd),
#endif
- INT2FIX(grp->gr_gid),
+ PW_GID2VAL(grp->gr_gid),
        mem);
}
Index: ext/etc/extconf.rb

RCS file: /cvs/ruby/src/ruby/ext/etc/extconf.rb,v
retrieving revision 1.6
diff -p -u -2 -r1.6 extconf.rb
--- ext/etc/extconf.rb 6 Sep 2005 23:35:15 -0000 1.6
+++ ext/etc/extconf.rb 26 Jun 2006 17:05:23 -0000
@@ -25,5 +25,18 @@ if a or b or c
   have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
   have_struct_member('struct group', 'gr_passwd', 'grp.h')
- have_type("uid_t");
+ have_header("lastlog.h") and have_header("paths.h")
+ [%w"uid_t pwd.h", %w"gid_t grp.h"].each do |t, h|
+ if have_type(t, ["sys/types.h", h])
+ if try_static_assert("sizeof(#{t}) > sizeof(long)")
+ f = "LL2NUM"
+ else
+ f = "INT2NUM"
+ end
+ if try_static_assert("(#{t})-1 > 0")
+ f = "U#{f}"
+ end
+ $defs.push("-DPW_#{t.chomp('_t').upcase}2VAL=#{f}")
+ end
+ end
   create_makefile("etc")
end

--
Nobu Nakada

Hi,

At Tue, 27 Jun 2006 02:08:15 +0900,
nobu@ruby-lang.org wrote in [ruby-talk:199131]:

At Tue, 27 Jun 2006 00:06:18 +0900,
Ryan McGovern wrote in [ruby-talk:199102]:
> I beleve there is a bug in Etc.getpwnam. On our OS X server
> running 10.4 with ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0]
> we use AD for user management.

Does this help?

Sorry, the patch for extconf.rb was wrong.

* ext/etc/etc.c (setup_passwd, setup_group): allow bignum uid, gid and
  so on. [ruby-talk:199102]

Index: ext/etc/etc.c

···

===================================================================
RCS file: /cvs/ruby/src/ruby/ext/etc/etc.c,v
retrieving revision 1.22
diff -p -u -2 -r1.22 etc.c
--- ext/etc/etc.c 20 Jun 2006 18:02:14 -0000 1.22
+++ ext/etc/etc.c 26 Jun 2006 16:53:48 -0000
@@ -77,6 +77,6 @@ setup_passwd(struct passwd *pwd)
        safe_setup_str(pwd->pw_passwd),
#endif
- INT2FIX(pwd->pw_uid),
- INT2FIX(pwd->pw_gid),
+ PW_UID2VAL(pwd->pw_uid),
+ PW_GID2VAL(pwd->pw_gid),
#ifdef HAVE_ST_PW_GECOS
        safe_setup_str(pwd->pw_gecos),
@@ -85,8 +85,8 @@ setup_passwd(struct passwd *pwd)
        safe_setup_str(pwd->pw_shell),
#ifdef HAVE_ST_PW_CHANGE
- INT2FIX(pwd->pw_change),
+ INT2NUM(pwd->pw_change),
#endif
#ifdef HAVE_ST_PW_QUOTA
- INT2FIX(pwd->pw_quota),
+ INT2NUM(pwd->pw_quota),
#endif
#ifdef HAVE_ST_PW_AGE
@@ -100,5 +100,5 @@ setup_passwd(struct passwd *pwd)
#endif
#ifdef HAVE_ST_PW_EXPIRE
- INT2FIX(pwd->pw_expire),
+ INT2NUM(pwd->pw_expire),
#endif
        0 /*dummy*/
@@ -302,5 +302,5 @@ setup_group(struct group *grp)
        safe_setup_str(grp->gr_passwd),
#endif
- INT2FIX(grp->gr_gid),
+ PW_GID2VAL(grp->gr_gid),
        mem);
}
Index: ext/etc/extconf.rb

RCS file: /cvs/ruby/src/ruby/ext/etc/extconf.rb,v
retrieving revision 1.6
diff -p -u -2 -r1.6 extconf.rb
--- ext/etc/extconf.rb 6 Sep 2005 23:35:15 -0000 1.6
+++ ext/etc/extconf.rb 26 Jun 2006 17:05:23 -0000
@@ -25,5 +25,18 @@ if a or b or c
   have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
   have_struct_member('struct group', 'gr_passwd', 'grp.h')
- have_type("uid_t");
+ [%w"uid_t pwd.h", %w"gid_t grp.h"].each do |t, *h|
+ h << "sys/types.h"
+ if have_type(t, h)
+ if try_static_assert("sizeof(#{t}) > sizeof(long)", h)
+ f = "LL2NUM"
+ else
+ f = "INT2NUM"
+ end
+ if try_static_assert("(#{t})-1 > 0", h)
+ f = "U#{f}"
+ end
+ $defs.push("-DPW_#{t.chomp('_t').upcase}2VAL=#{f}")
+ end
+ end
   create_makefile("etc")
end

--
Nobu Nakada

Hi,

···

In message "Re: Large uid's with Etc.getpwnam" on Tue, 27 Jun 2006 02:22:36 +0900, nobu@ruby-lang.org writes:

* ext/etc/etc.c (setup_passwd, setup_group): allow bignum uid, gid and
so on. [ruby-talk:199102]

Commit the fix please.

              matz.