Ruby: SMB/CIFS 共有をブラウズ

Post Perl は Ruby に決定。 た〜だ〜い〜ま〜勉強中〜♪ 本日 4日目。 久しぶりの勉強のためか脳疲労が激しいけど、楽しい〜♪ 当然のように特有のクセがあって苦労しているけど、 どのクセも何故そのようになっているかの理由が感じられるし、 何より違和感や不快感がない! 慣れれば慣れるほど、さらに気持ちよくコーディングできそう。 Perl や PHP や Python やシェルでコーディングしていると、 違和感・不快感を感じることしきりだもんなぁ。

実は Ruby の勉強と平行して Samba 共有内のファイル検索ツールを今月中に作らねばならないのだけど、間に合うかしら!? いや、間に合わせねば。 Ruby の素晴しさを引き出すには時間が足りないかもしれないけど、 そこそこは使い熟せそうな感触を得ている。

初 Ruby スクリプトは以下のような感じ。突っ込み歓迎。 Ruby/SMB を利用して SMB 共有内の特定の拡張子のファイルを一覧表示する Ruby スクリプト:

#!/usr/bin/ruby -w

require "smb"

## Override SMB::Dir::Entry#url to hide "user:password" in URL
class SMB::Dir::Entry
  alias original_url url
  private :o riginal_url
  def url
    return original_url.sub(%r#^([^/:]+://)(?:[^/]+@)?#, '\1')
  end
end

$ext = %w(odt ods odp doc xls ppt pdf txt htm html)
$server = "127.0.0.1"
$user = "testuser"
$password = "testuserpassword"
$server.downcase!
$auth = [nil, $user, $password]
$ext_re = Regexp.new("\\.(#{$ext.join("|")})$", Regexp::IGNORECASE)

def crawl(dir)
  dir.direntries.each do |entry|
    next if entry.name =~ /^\.\.?$/
    ## FIXME: SIGSEGV protector (libsmbclient's bug?)
    next if entry.url.length > 1000
    if entry.file?
      if entry.url =~ $ext_re
        puts entry.url
      end
    elsif entry.dir?
      begin
        entry_dir = entry.open
        crawl(entry_dir)
      rescue => e
        e_message = e.to_s.sub(/ - smb:\/\/.*/, '')
        STDERR.puts "#{$0}: cannot open directory: #{entry.url}: #{e_message}"
      ensure
        entry_dir.close if entry_dir
      end
    end
  end
end

SMB.on_authentication do |server, share, workgroup, user, password|
  $auth
end

begin
  server = SMB.open("smb://#{$server}/")
  #server = SMB.open("smb://#{$user}:#{$password}@#{$server}/")
rescue => e
  STDERR.puts "#{$0}: cannot connect to server: #{$server}: #{e}"
  exit 1
end
server.direntries.each do |entry|
  if entry.file_share?
    begin
      entry_share = entry.open
      crawl(entry_share)
    rescue => e
      STDERR.puts "#{$0}: cannot connect to share: #{entry.name}: #{e}"
    ensure
      entry_share.close if entry_share
    end
  end
end

exit 0

以下は Ruby/SMB beta3 用のパッチで、 SMB.on_authentication のバグ修正とログレベルを 0 に変更する修正:

--- rubysmb-beta-3/rubysmb.c.dist   2002-10-17 20:13:48.000000000 +0900
+++ rubysmb-beta-3/rubysmb.c    2007-06-05 23:52:11.698527382 +0900
@@ -112,9 +112,9 @@ static void auth_fn(const char *server,
 if (RARRAY(ary)->len != 3) {
   rb_raise(eSmbError, "array should contain workgroup, username and password to use as authentication");
 }
-
-  wg = RARRAY(ary)->ptr[1];
-  un = RARRAY(ary)->ptr[0];
+
+  wg = RARRAY(ary)->ptr[0];
+  un = RARRAY(ary)->ptr[1];
   pw = RARRAY(ary)->ptr[2];
   if (!NIL_P(wg)) {
@@ -167,7 +167,7 @@ void Init_smb()
 {
   int err;
-  err = smbc_init(auth_fn, 1);
+  err = smbc_init(auth_fn, 0);
   if (err < 0) {
     rb_raise(rb_eRuntimeError, "Error loading libsmbclient: %s\n", strerror(errno));
   }
add to hatena hatena.comment (1) add to del.icio.us (0) add to livedoor.clip (0) add to Yahoo!Bookmark (1) Total: 2

コメントを書く

Your email is never shared. * 印の項目は必須項目です。

*
*