Who Wants to Be a Scripting Guy?


#1

So asks Dr. Scripto at Microsoft TechNet

http://www.microsoft.com/technet/scriptcenter/funzone/puzzle/default.mspx

At the very bottom, they say, “Or ? and it pains us to say this ? could
this be our fault? What?s wrong with this script?”

Well, it’s obvious: the script is not written in Ruby.

Maybe they need a few decent Ruby solutions.


James B.

http://web2.0validator.com - We’re the Dot in Web 2.0
http://refreshingcities.org - Design, technology, usability
http://yourelevatorpitch.com - Finding Business Focus
http://www.jamesbritt.com - Playing with Better Toys


#2

It seems as if the whole point of that column is explaining annoying
idiosyncrasies of VBScript and Windows. It reminds me of those little
C or C++ challenges where you are supposed to spot some crazy bug that
essentially requires you to be a human compiler.

I think I’ll stick with Ruby.

Ryan


#3

James B. wrote:

Well, it’s obvious: the script is not written in Ruby.

Maybe they need a few decent Ruby solutions.

It’s a good question.

Wouldn’t it be nice to have a cross-platform way of asking “how much
disk space is available here?”

Java’s doing it soon!
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4057701

Is there a way of using df that’s consistent across Linuxes/BSDs/Mac (-k
perhaps?)

Here’s a start:

class << self
define_method :bytes_free, &begin
require ‘Win32API’
df = Win32API.new(“kernel32”, “GetDiskFreeSpaceEx”, “pppp”, “i”)
proc do |dir|
df.call(dir, ret=" ", " ", " "); ret.unpack(“L”)[0]
end
rescue LoadError
proc do |dir|
df -k #{dir}[/\n.{20} (\d+)/, 1].to_i
end
end
end

p bytes_free(".")
p bytes_free(“some/other/path”)

Cheers,
Dave


#4

Dave B. wrote:

Well, it’s obvious: the script is not written in Ruby.

Maybe they need a few decent Ruby solutions.

It’s a good question.
I’m not sure about that. Unless I’m very much mistaken, the problem
with the script is that Windows has a nasty reaction to being asked the
free space available on a CD drive when there’s no CD in it. Blech. It
makes the drive ‘partially available’ - some things work, others don’t.
If I’m right about that, then what’s needed is a way to find out which
drives can respond before asking them to do so.

On unices, I think this does the trick:

$ df -h mount | grep '^/dev' | cut -f 3 -d ' '

Works on Linux and OS X, certainly - I don’t have any other BSDs to
check.


#5

On May 19, 2006, at 12:43 AM, Alex Y. wrote:

Dave B. wrote:

On unices, I think this does the trick:

$ df -h mount | grep '^/dev' | cut -f 3 -d ' '

Works on Linux and OS X, certainly - I don’t have any other BSDs to
check.

It should work on most modern *nix systems, but df -h isn’t
available on Solaris 8 and older. Incidentally, this was one of my
favorite changes in Solaris 9.

Paul K.


#6

Dave B. wrote:

  `df -k #{dir}`[/\n.{20} (\d+)/, 1].to_i

should be
df -k #{dir}[/\n.{20} (\d+)/, 1].to_i * 1024

Cheers,
Dave


#7

Paul K. wrote:

On May 19, 2006, at 12:43 AM, Alex Y. wrote:

Dave B. wrote:

On unices, I think this does the trick:

$ df -h mount | grep '^/dev' | cut -f 3 -d ' '

Works on Linux and OS X, certainly - I don’t have any other BSDs to
check.

It should work on most modern *nix systems, but df -h isn’t
available on Solaris 8 and older. Incidentally, this was one of my
favorite changes in Solaris 9.

Paul K.

I found a ruby version of df a long time ago. It did a syscall(99), so
if this syscall is a standard POSIX one then the script should work on
all posix compliant os-es
The relevant part:
size = 64
unpack_fmt = ‘iiiiiiiiiiiiiiii’
foo = ’ ’ * size
syscall(99, hd[1], foo)
type, @bsize, @blocks, @bfree, @bavail, @files, @ffree,
tmp,tmp,@namelen = foo.unpack(unpack_fmt)
usage=100*(@blocks-@bfree)/@blocks


#8

Alex Y. wrote:

Dave B. wrote:

It’s a good question.
I’m not sure about that. Unless I’m very much mistaken, the problem
with the script is that Windows has a nasty reaction to being asked the
free space available on a CD drive when there’s no CD in it. Blech. It
makes the drive ‘partially available’ - some things work, others don’t.
If I’m right about that, then what’s needed is a way to find out which
drives can respond before asking them to do so.

You are right, and the answer to this simple problem is to check the
result of objDrive’s IsReady method, but I was talking about the
question behind the question: can we determine disk free space in Ruby?

On unices, I think this does the trick:

$ df -h mount | grep '^/dev' | cut -f 3 -d ' '

Works on Linux and OS X, certainly - I don’t have any other BSDs to check.

As I said, I think it would be very handy to have a cross-platform way
of checking disk free space from Ruby. The most useful thing to me seems
a function that takes a path and returns the number of bytes available
there, so that’s what I posted. I tested it on a couple of Linuxes with
different "df"s, so I’m not confident my solution will work across posix
platforms.

Cheers,
Dave


#9

Edwin van Leeuwen wrote:

  usage=100*(@blocks-@bfree)/@blocks

In the above code, what’s hd? And would this be more or less portable
than my suggestion?

df -k #{dir}[/\n.{20} (\d+)/, 1].to_i * 1024

(Does this work on your *nix?)

Cheers,
Dave


#10

Dave B. wrote:

In the above code, what’s hd? And would this be more or less portable
than my suggestion?

df -k #{dir}[/\n.{20} (\d+)/, 1].to_i * 1024

(Does this work on your *nix?)

Cheers,
Dave
The hd is the mount point read from /etc/mtab

More or less portable is a difficult question, especially since I only
have linux experience. A quick google has turned up that syscall 99 is
the stafs syscall and that these are (at the least) available on Linux,
SunOS, HPUX, 4.4BSD and AIX. I don’t know if it works precisely the
same on all of them, but as far as I can see df also uses statfs to get
it’s info from.

I think it is at least as portable as using df, and probably more
portable, because it is not dependent on df syntax. My knowledge of
windows is very limited, but don’t they have limited posix support since
win NT?

On linux all system calls are defined here:
/usr/include/asm/unistd.h
As you can see 99 is statfs.

Edwin


#11

On May 19, 2006, at 5:13 AM, Paul K. wrote:

It should work on most modern *nix systems, but df -h isn’t
available on Solaris 8 and older. Incidentally, this was one of my
favorite changes in Solaris 9.

(Sorry for resurrecting an old thread.)

I found a solution that, based on my testing on both OSX and linux,
appears to work pretty well for UNIX. I’d like to hear if this works
on Solaris and FreeBSD/NetBSD/OpenBSD.

def self.list_devices(path = nil)
# call out to the underlying OS and figure out all the devices
on the system
df_output = df -l -P #{path}
df_vals = df_output.split(/\n/)
devices = []
df_vals.each do |val|
next unless val =~ /(.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.+)\s+(.+)/
device, total, used, avail, percentage, mount_point = $1, $2,
$3, $4, $5, $6
devices.push({
:device => device,
:total => total,
:used => used,
:avail => avail,
:percentage => percentage,
:mount_point => mount_point
})
end
devices
end