パスワードを忘れた? アカウント作成
518483 journal

oopsの日記: NTFSの件その4

日記 by oops

NTFSの圧縮によりファイルが壊れる件の続き。

チェックスクリプトを更新してみた。

ファイルが壊れるのは最後の部分のみが多いみたいで、前のスクリプトでは検出できない。1メガバイト以上のでかいファイルは壊れにくいけど(壊れた場合を見たことない)、数十キロバイト程度だと壊れる可能性がかなり高い。

出力は、

Broken?:4011:2:DF: t:/foo/bar.jpg

とか出るけど、Broken? は壊れたかもしれないというメッセージ、4011はファイルサイズ、2は可能性レベルで1より2の方が壊れてる可能性高い、DFは壊れたときに埋め込まれるコードでDFの場合はほぼ壊れたとみていい、それ以外の場合は壊れてない可能性が高い。ファイル末尾に00が並ぶ正常なファイルが多数あるので検出しないようにしてる。

検出性を優先しているので壊れてないファイルも出力される。ただ、壊れたファイルをすべて検出してくれるわけでもない。出力されたファイルはバイナリエディタで自分なりに検証することが必要。

今回も Ruby スクリプトだけど、C だと Find.find 相当のことやるとソースがかなりでかくなるし。

Microsoft からバグフィクスとともに壊れたファイルを検出してくれるツールも出してくれるのを期待。これはそれまでのつなぎと言うことで。

#!/usr/local/bin/ruby
 
require 'find'
 
def scan_broken(path,tail)
  bsize = 1024
  c0 = nil
  begin
    File.open(path,'rb') do |f|
      f.seek(-tail,IO::SEEK_END) if tail != nil
      c0 = f.getc
      while buf = f.read(bsize)
        buf.each_byte do |c|
          return :ok if c != c0
        end
      end
    end
  rescue
    return :err
  end
  return c0
end
 
def check_broken(path,size,aus=4096,min_tail=3000)
  level = nil
  tail = size % aus
  tail = aus if tail == 0
  if tail < min_tail
    tail = min_tail
    level = 1
  else
    level = 2
  end
  result = scan_broken(path,tail)
  if result != :ok && result != :err && result != 0
    return [level,result]
  else
    return [0,0]
  end
end
 
def printm(buf,ios,is_flush=true)
  ios.each do |io|
    if io != nil
      io.print(buf)
      io.flush if is_flush
    end
  end
end
 
logfile = File.open("00check.log",'w')
aus = 4096
min_tail = 3000
$*.each do |root|
  Find.find(root) do |path|
    next if !test(?f,path)
    st = File.stat(path)
    next if st == nil || st.size < min_tail
    level, code = check_broken(path,st.size,aus,min_tail)
    if level > 0
      printm("Broken?:#{st.size}:#{level}:#{format('%X',code)}: #{path}\n",[logfile,STDOUT])
    end
  end
end
logfile.close

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

皆さんもソースを読むときに、行と行の間を読むような気持ちで見てほしい -- あるハッカー

読み込み中...