# Trying to get stat, Win32API to work

**URL:** <https://www.ruby-forum.com/t/trying-to-get-stat-win32api-to-work/93375>\
**Category:** Ruby\
**Created:** [March 31, 2006, 10:49pm UTC](https://www.ruby-forum.com/t/trying-to-get-stat-win32api-to-work/93375 "2006-03-31T22:49:00Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![BergerS\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BergerS\_Daniel](https://www.ruby-forum.com/u/BergerS_Daniel)\
**Post date:** [March 31, 2006, 10:49pm UTC](https://www.ruby-forum.com/t/trying-to-get-stat-win32api-to-work/93375/1 "2006-03-31T22:49:00Z")

</div>

Hi all,

Ruby 1.8.4  
Windows XP

I’m trying to make a pure Ruby version of File::Stat. Something seems  
to go wrong around the time I get rdev. I think I just need another set  
of eyes to see what I’m doing wrong here.

Thanks,

Dan

# stat.rb

require ‘Win32API’

# Based on what I see in sys/types.h:

# 

# ino\_t - unsigned short

# dev\_t - unsigned int

# off\_t - long

# time\_t - long

=begin  
struct \_stat {  
\_dev\_t st\_dev; # ‘I’, 4  
\_ino\_t st\_ino; # ‘S’, 2  
unsigned short st\_mode; # ‘S’, 2  
short st\_nlink; # ‘s’, 2  
short st\_uid; # ‘s’, 2  
short st\_gid; # ‘s’, 2  
\_dev\_t st\_rdev; # ‘I’, 4  
\_off\_t st\_size; # ‘l’, 4  
time\_t st\_atime; # ‘l’, 4  
time\_t st\_mtime; # ‘l’, 4  
time\_t st\_ctime; # ‘l’, 4  
};  
=end

class File::Stat  
@@stat = Win32API.new(‘msvcrt’, ‘\_stat’, ‘PP’, ‘I’)

def initialize(file)  
stat\_buf = [0,0,0,0,0,0,0,0,0,0,0].pack(‘ISSsssIllll’)

```
  @@stat.call(file, stat_buf)

  @dev = stat_buf[0..3].unpack('I').first
  @ino = stat_buf[4..5].unpack('S').first
  @mode = stat_buf[6..7].unpack('S').first
  @nlink = stat_buf[8..9].unpack('s').first
  @uid = stat_buf[10..11].unpack('s').first
  @gid = stat_buf[12..13].unpack('s').first
  @rdev = stat_buf[14..17].unpack('I').first
  @size = stat_buf[18..21].unpack('l').first
  @atime = stat_buf[22..25].unpack('l').first
  @mtime = stat_buf[26..29].unpack('l').first
  @ctime = stat_buf[30..33].unpack('l').first

  puts "Dev: [#{@dev}]"
  puts "Ino: [#{@ino}]"
  puts "Mode: [#{@mode}]"
  puts "Nlink: [#{@nlink}]"
  puts "Uid: [#{@uid}]"
  puts "Gid: [#{@gid}]"
  puts "RDev: [#{@rdev}]" # Things start to look wrong here...
  puts "Size: [#{@size}]"
  puts "Atime: [" + Time.at(@atime) + "]"
  puts "Mtime: [" + Time.at(@mtime) + "]"
  puts "Ctime: [" + Time.at(@ctime) + "]"

```

end  
end

if $0 == **FILE**  
File::Stat.new(‘somefile.txt’)  
end

---

<div class="post-metadata">

**Author:** ![BergerS\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BergerS\_Daniel](https://www.ruby-forum.com/u/BergerS_Daniel)\
**Post date:** [April 1, 2006, 1:18am UTC](https://www.ruby-forum.com/t/trying-to-get-stat-win32api-to-work/93375/2 "2006-04-01T01:18:58Z")

</div>

Hi,

> I’m trying to make a pure Ruby version of File::Stat. Something seems  
> to go wrong around the time I get rdev. I think I just need another set  
> of eyes to see what I’m doing wrong here.
> 
> Thanks,
> 
> Dan
> 
> # stat.rb

…

> 

It is due to the structure alignment.  
Applications should generally align structure members at addresses that  
are  
¡°natural¡± for the data type and the processor involved. For example, a  
4-byte data member should have an address that is a multiple of four.

Refer to

> **[Technical documentation](https://learn.microsoft.com/en-us/docs/)**

Your code should be like this:

# stat.rb

require ‘Win32API’

# Based on what I see in sys/types.h:

# 

# ino\_t - unsigned short

# dev\_t - unsigned int

# off\_t - long

# time\_t - long

=begin  
struct \_stat {  
\_dev\_t st\_dev; # ‘I’, 4  
\_ino\_t st\_ino; # ‘S’, 2  
unsigned short st\_mode; # ‘S’, 2  
short st\_nlink; # ‘s’, 2  
short st\_uid; # ‘s’, 2  
short st\_gid; # ‘s’, 2  
short padding; # ‘s’, 2 —\> invisible padding 2 bytes  
for  
structure alignment  
\_dev\_t st\_rdev; # ‘I’, 4  
\_off\_t st\_size; # ‘l’, 4  
time\_t st\_atime; # ‘l’, 4  
time\_t st\_mtime; # ‘l’, 4  
time\_t st\_ctime; # ‘l’, 4  
};  
=end

class File::Stat  
@@stat = Win32API.new(‘msvcrt’, ‘\_stat’, ‘PP’, ‘I’)

def initialize(file)  
stat\_buf = [0,0,0,0,0,0,0,0,0,0,0,0].pack(‘ISSssssIllll’)

```
  @@stat.call(file, stat_buf)

  @dev = stat_buf[0..3].unpack('I').first
  @ino = stat_buf[4..5].unpack('S').first
  @mode = stat_buf[6..7].unpack('S').first
  @nlink = stat_buf[8..9].unpack('s').first
  @uid = stat_buf[10..11].unpack('s').first
  @gid = stat_buf[12..13].unpack('s').first
  @rdev = stat_buf[16..19].unpack('I').first
  @size = stat_buf[20..23].unpack('l').first
  @atime = stat_buf[24..27].unpack('l').first
  @mtime = stat_buf[28..31].unpack('l').first
  @ctime = stat_buf[32..35].unpack('l').first

  puts "Dev: [#{@dev}]"
  puts "Ino: [#{@ino}]"
  puts "Mode: [#{@mode}]"
  puts "Nlink: [#{@nlink}]"
  puts "Uid: [#{@uid}]"
  puts "Gid: [#{@gid}]"
  puts "RDev: [#{@rdev}]" # Things start to look wrong here...
  puts "Size: [#{@size}]"
  puts "Atime: [" + Time.at(@atime).to_s + "]"
  puts "Mtime: [" + Time.at(@mtime).to_s + "]"
  puts "Ctime: [" + Time.at(@ctime).to_s + "]"

```

end  
end

if $0 == **FILE**  
File::Stat.new(‘r.rb’)  
end

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![BergerS\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/bc8723/32.png) [@BergerS\_Daniel](https://www.ruby-forum.com/u/BergerS_Daniel)\
**Post date:** [April 1, 2006, 4:27am UTC](https://www.ruby-forum.com/t/trying-to-get-stat-win32api-to-work/93375/3 "2006-04-01T04:27:06Z")

</div>

Park H. wrote:

> > Ruby 1.8.4
> > 
> > # stat.rb
> 
> Your code should be like this:

Aha! Thanks!

Dan
