Trying to get stat, Win32API to work


#1

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


#2

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
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_structure_alignment.asp

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.


#3

Park H. wrote:

Ruby 1.8.4

stat.rb

Your code should be like this:

Aha! Thanks!

Dan