$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) require 'open-uri' require 'RipXploreLog' class FileSystemImage attr_reader :file_system, :image_format,:filename attr_accessor :volume_name def FileSystemImage.is_file_system_image_filename?(filename) extension=File.extname(File.basename(filename,".gz")).downcase RipXploreLog.debug("checking if is file system image filename - #{filename} (extension #{extension})") RipXploreLog.debug(ImageFormat.all_possible_extensions.join(";")) ImageFormat.all_possible_extensions.include?(extension) end #given a bytestream (and, optionally, filename the bytes are from), return the class that is the best match for this class def FileSystemImage.best_fit(file_bytes,filename=nil) candidates=[] file_ext=File.extname(filename.sub(/\.gz$/,"")).downcase RipXploreLog.debug("looking for best fit for image format for #{filename} : extension #{file_ext}") ImageFormat.all_image_formats.each do |image_format| if !file_ext.nil? && !image_format.possible_extensions.include?(file_ext) then RipXploreLog.debug("skipping #{image_format} - unmatched extension #{file_ext}") else image_format.possible_file_systems.each do |file_system| RipXploreLog.debug("checking image format #{image_format} and file system #{file_system}") candidate=FileSystemImage.new(file_bytes,file_system,image_format,filename) RipXploreLog.debug("score - #{candidate.compatability_score}") candidates<a.compatability_score}[0] RipXploreLog.debug("best candidate = #{best_candidate.file_system}/#{best_candidate.image_format} score: #{best_candidate.compatability_score}") best_candidate end @compatability_score=nil def compatability_score if @compatability_score.nil? then image_format_compatability_score=image_format.compatability_score(self) if image_format_compatability_score>0 then #if we don't have a valid image_format, don't bother checking the file_system! file_system_compatability_score=file_system.compatability_score(self) @compatability_score=file_system_compatability_score*image_format_compatability_score else @compatability_score=0 end end @compatability_score end def file_bytes return image_format.file_bytes end def get_sector(track,sector) image_format.get_sector(track,sector) end def set_sector(track,sector,sector_contents) raise "#{image_format} image updates not supported (yet)" unless image_format.respond_to?(:set_sector) image_format.set_sector(track,sector,sector_contents) end #how many tracks are in this particular image? def track_count image_format.track_count end def initialize(file_bytes,file_system,image_format,filename=nil) @file_bytes=file_bytes @file_system=file_system @image_format=image_format.new(file_bytes) @filename=filename @files=file_system.files(self) if compatability_score>0 end def files @files=file_system.files(self) if @files.nil? @files.flatten end #return an array containing a list of numbers of valid tracks on this image def track_list image_format.track_list end #return a list of all valid sectors in the specified track on this image def sectors_in_track(track_no) image_format.sectors_in_track(track_no) end def start_track image_format.host_system.start_track end def end_track image_format.end_track end def to_hex_dump s="" track_list.each {|track| s<