#!/usr/bin/env ruby # $Id: cd-read.rb,v 1.12 2008/05/02 13:05:39 karl Exp $ # # A program to read CD blocks. See read-cd from the libcdio distribution # more complete program. # Copyright (C) 2006, 2007, 2008 Rocky Bernstein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . mypath = File.dirname(__FILE__) if(File::exists?(mypath + "/../lib/cdio.rb")) $: << File.dirname(__FILE__) + '/../lib' $: << File.dirname(__FILE__) + '/../ext/cdio' else require 'rubygems' end require "cdio" require 'getoptlong' # Print short help - the command form and a one-line description. def usage() puts "%s --mode *mode* [options] [device] Read blocks of a CD" % $0 end # Print help (includes usage), option descriptions, and then exit. def help usage puts puts "Options are ..." puts OPTIONS.sort.each do |long, short, mode, desc| if mode == GetoptLong::REQUIRED_ARGUMENT if desc =~ /\b([A-Z]{2,})\b/ long = long + "=#{$1}" end end printf " %-20s (%s)\n", long, short printf " %s\n", desc end exit 100 end read_modes = { 'audio' => Rubycdio::READ_MODE_AUDIO, 'm1f1' => Rubycdio::READ_MODE_M1F1, 'm1f2' => Rubycdio::READ_MODE_M1F2, 'm2f1' => Rubycdio::READ_MODE_M2F1, 'm2f2' => Rubycdio::READ_MODE_M2F2, 'data' => nil } # Standard C library's isprint() in Ruby def isprint(c) /[[:print:]]/ === c.chr end # Print a hex dump and string interpretation of buffer. # If just_hex is true, then show only the hex dump. def hexdump (buffer, just_hex=false) for i in 0 .. buffer.length - 1 if i % 16 == 0 printf "0x%04x: ", i end printf "%02x", buffer[i] printf " " if i % 2 == 1 if i % 16 == 15 if !just_hex printf " " for j in i-15 .. i printf "%s", isprint(buffer[j]) ? buffer[j].chr : '.' end end printf "\n" end end print "\n" end # Return a list of the command line options supported by the # program. def command_line_options OPTIONS.collect { |lst| lst[0..-2] } end OPTIONS = [ ['--help', '-h', GetoptLong::NO_ARGUMENT, "Display this help message."], ["--mode", "-m", GetoptLong::REQUIRED_ARGUMENT, "CD Reading mode: audio, m1f1, m1f2 m2f1 or m2f2"], ["--start", "-s", GetoptLong::REQUIRED_ARGUMENT, "Starting block"], ["--number", "-n", GetoptLong::REQUIRED_ARGUMENT, "Number of blocks"] ] options={} options['--start'] = 1 options['--number'] = 1 options['--mode'] = nil opts = GetoptLong.new(*command_line_options) begin opts.each { |opt, value| options[opt]=value } rescue GetoptLong::InvalidOption exit 3 end help if options["--help"] if not options['--mode'] puts "Mode option must given (and one of audio, m1f1, m1f2, m1f2 or m1f2)." exit(1) end begin read_mode = read_modes[options['--mode']] rescue KeyError puts "Need to use the --mode option with one of audio, m1f1, m1f2, m1f2 or m1f2" exit 1 end # While sys.argv[0] is a program name and sys.argv[1] the first # option, argv[0] is the first unprocessed option -- roughly # the equivalent of sys.argv[1]. if ARGV.length() > 1 begin d = Cdio::Device.new(ARGV.first) rescue IOError puts "Problem opening CD-ROM: %s" % argv[0] exit(1) end else begin d = Cdio::Device.new(nil, Rubycdio::DRIVER_UNKNOWN) rescue IOError puts "Problem finding a CD-ROM" exit(1) end end ## All this setup just to issue this one of these commands. if read_mode == nil blocks, data=d.read_data_blocks(options['--start'].to_i, options['--number'].to_i) else blocks, data=d.read_sectors(options['--start'].to_i, read_mode, options['--number'].to_i) end if data hexdump data end