Trying to get stat, Win32API to work

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

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

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.

Park H. wrote:

Ruby 1.8.4

stat.rb

Your code should be like this:

Aha! Thanks!

Dan