#!/usr/bin/perl # (c)2003 Marc Alexander Lehmann use Getopt::Long; use Linux::NBD; use Linux::NBD::Client; use Linux::NBD::Server; Getopt::Long::Configure ("bundling", "no_ignore_case"); my $device = undef; my $image = undef; my $offset = undef; my $size = undef; my $mount = undef; my $verbose = 0; GetOptions ( "device|d=s" => \$device, "image|i=s" => \$image, "offset|o=i" => \$offset, "size|s=i" => \$size, "verbose|v" => \$verbose, "mount|m=s" => \$mount, "help|h|?" => sub { require Pod::Usage; Pod::Usage::pod2usage(-exitstatus => 0, verbose => 2); }, ) or exit 1; defined $device || defined $image or die "You must specify one (or both) of the -d or -i switches. Use --help.\n"; # open an nbd device my $client = new Linux::NBD::Client device => $device; # clear it $client->clear_queue; $client->disconnect; $client->socket(undef); if (defined $image) { # now attach the file open IMAGE, "<", $image or die "$image: $!"; unless (defined $offset and defined $size) { require v5.8; # guess sysread IMAGE, my $buf, 2352*100; # find two volume descriptors... there _should_ be two ;) # ISO has CD001, we ignore high sierra $buf =~ /\001CD001\001/g or die "unable to guess: no primary volume descriptor found"; my $ofs1 = $-[0]; $buf =~ /[\000\001\002\377]CD001\001/g or die "unable to guess: no second volume descriptor found"; my $ofs2 = $-[0]; $size = $ofs2 - $ofs1; $offset = $ofs1 - 16 * $size; # adjust offset so that sector 16 is the first volume header always. printf "\nGuessed blocksize %d and offset 0x%04x\n", $size, $offset; } my ($a, $b) = Linux::NBD::tcp_socketpair; # cleanup cleanly. oops ;) $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub { exit }; # set the socket and fork the client service process $client->set_blocksize(2048); $client->set_size(-s IMAGE); $client->socket($a); $client->run_async; $device = $client->device; if (defined $mount) { print "Running mount (you have to unmount yourself)\n"; exec "mount", "-tiso9660", "-oro", $device, $mount if fork == 0; print "Everything set up, starting server\n"; } else { print <new(socket => $b); $server->run; # never returns } BEGIN { @Server::ISA = Linux::NBD::Server::; }; # implement only read requests (we emulate a primitive cdrom...) sub Server::req_read { my ($self, $handle, $ofs, $len) = @_; my ($ofs_l, $ofs_h) = ($ofs & 2047, $ofs >> 11); printf "READ %08x \@%08x (block $ofs_h+$ofs_l)\n", $len, $ofs if $verbose > 0; $self->reply($handle); while ($len) { sysseek IMAGE, ($ofs_h * $size) + $ofs_l + $offset, 0 or die "$image: $!"; $ofs_l = 2048 - $ofs_l; $ofs_l < $len or $ofs_l = $len; sysread IMAGE, my $buf, $ofs_l; $ofs_l == length $buf or $buf = "\x0" x $ofs_l; $self->send($buf); $len -= $ofs_l; $ofs_l = 0; $ofs_h++; } } =head1 NAME attach-bincue - attach a .bin (cdrom image) containing an iso9660 fs to nbd =head1 SYNOPSIS attach-bincue -i iso9660.bin -m /mnt & # start server # kill server umount /mnt attach-bincue -d /dev/ndx # disconnect server =head1 DESCRIPTION With the C<-i> switch, attaches a C<.bin> file (containing an iso 9660 filesystem image in the bin/cue "fileformat") to a nbd instance and serve requests. Otherwise the nbd device specified with C<-d> is sent a disconnect request, usually causing it to exit cleanly. Despite the name of this program, many more image formats can be attached due to the guessing code - I have successfully mounted nero-nrg, clonecd-img, blindwrite, uncompressed .fcd and a few more formats. =head1 ARGUMENTS =over 4 =item --image binfile Attached the given file to the network block device and serve requests. The command will only exit on disconnect or any fatal errors. =item --offset bytes The ISO image is offset by the given number of bytes. The default is to guess. Common values are C<24>, C<8> and C<0>. =item --size blocksize The blocksize in bytes. The default is to guess. Common values are C<2352>, C<2332> and C<2340>. =item --device /dev/ndx The nbd device node to use. C automatically looks for a unused one if this switch isn't given. =item --verbose Increase verbosity. With this switch, read requests will be logged to stdout. =item --mount path Try to mount the CD as iso image on the given path. =back =head1 EXAMPLES Common combinations of offset and blocksize attach-bincue -b 2352 -o 24 attach-bincue -b 2332 -o 8 attach-bincue -b 2340 -o 0 =head1 AUTHOR Marc Lehmann .