From: noreply@... Date: 2007-01-12T06:26:26+09:00 Subject: [ ruby-Patches-7760 ] Fix for File and File::Stat to deal with bogus stat.st_size member Patches item #7760, was opened at 2007-01-11 14:26 You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1700&aid=7760&group_id=426 Category: Ruby1.8 Group: None Status: Open Resolution: None Priority: 3 Submitted By: Daniel Berger (djberg96) Assigned to: Nobody (None) Summary: Fix for File and File::Stat to deal with bogus stat.st_size member Initial Comment: Hi all, It seems that the stat() function has a bug on Solaris 10 (06/06) where it doesn't set the st_size value to NULL for character or block devices. Instead, it seems to default to INT_MAX, which results in bogus information returned by File::Stat. For example: irb(main):001:0> File.stat("/dev/fd0").size => 9223372036854775807 That should return 0. This has been reported on sunsolve.sun.com (bug 4013608), but I'm not positive if it's been patched yet, or if it affects other Solaris versions, because I don't have a sunsolve account (i.e. I can see the ticket summary but not the details). This affects the following methods: File::Stat#size File::Stat#size? File::Stat#zero? File.size File.size? File.zero? I'm not sure if you take patches for bugs in the underlying OS or not. If you do accept them, here's the patch. I've also included a small test suite that now passes on my Solaris box. Note that I've only added explicit comments on the approach I use here in one function (rb_stat_size). Copy and paste if you would like it added to each of the functions. --- file.orig Tue Jan 9 10:57:09 2007 +++ file.c Thu Jan 11 14:08:34 2007 @@ -467,7 +467,15 @@ rb_stat_size(self) VALUE self; { - return OFFT2NUM(get_stat(self)->st_size); + struct stat *st = get_stat(self); + + /* Block and character devices are handled explicitly because some + * platforms set the st_size member to an incorrect value. + */ + if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + return INT2FIX(0); + + return OFFT2NUM(st->st_size); } /* @@ -1257,7 +1265,9 @@ struct stat st; if (rb_stat(fname, &st) < 0) return Qfalse; - if (st.st_size == 0) return Qtrue; + if (st.st_size == 0 || S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) + return Qtrue; + return Qfalse; } @@ -1276,7 +1286,9 @@ struct stat st; if (rb_stat(fname, &st) < 0) return Qnil; - if (st.st_size == 0) return Qnil; + if (st.st_size == 0 || S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) + return Qnil; + return OFFT2NUM(st.st_size); } @@ -1481,7 +1493,11 @@ struct stat st; if (rb_stat(fname, &st) < 0) - rb_sys_fail(StringValueCStr(fname)); + rb_sys_fail(StringValueCStr(fname)); + + if( S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) ) + return INT2FIX(0); + return OFFT2NUM(st.st_size); } @@ -3981,7 +3997,10 @@ rb_stat_z(obj) VALUE obj; { - if (get_stat(obj)->st_size == 0) return Qtrue; + struct stat *st = get_stat(obj); + if (st->st_size == 0 || S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + return Qtrue; + return Qfalse; } @@ -4000,10 +4019,11 @@ rb_stat_s(obj) VALUE obj; { - off_t size = get_stat(obj)->st_size; + struct stat *st = get_stat(obj); + if (st->st_size == 0 || S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + return Qnil; - if (size == 0) return Qnil; - return OFFT2NUM(size); + return OFFT2NUM(st->st_size); } /* ---------------------------------------------------------------------- You can respond by visiting: http://rubyforge.org/tracker/?func=detail&atid=1700&aid=7760&group_id=426