From aab2816dd9ba12a1b9977da56cc18b985c499f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 28 Oct 2014 15:27:22 +0100 Subject: [PATCH] Add proper device size and name detection on Haiku Haiku does not support lseek(SEEK_END) on block devices. Well, actually it does but it seeks to the stat()-reported length, which is zero. --- Makefile.in | 5 +++-- ddrescue.h | 16 ++++++++++++++++ haiku.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ haiku.h | 19 +++++++++++++++++++ linux.cc | 4 ---- main.cc | 8 ++++---- 6 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 haiku.cc create mode 100644 haiku.h diff --git a/Makefile.in b/Makefile.in index de0c787..f713d1b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh ddobjs = fillbook.o genbook.o io.o logbook.o rescuebook.o main.o -objs = arg_parser.o block.o linux.o logfile.o loggers.o rational.o $(ddobjs) +objs = arg_parser.o block.o haiku.o linux.o logfile.o loggers.o rational.o $(ddobjs) logobjs = arg_parser.o block.o logbook.o logfile.o ddrescuelog.o @@ -42,13 +42,14 @@ $(objs) : Makefile $(ddobjs) : block.h ddrescue.h arg_parser.o : arg_parser.h block.o : block.h +haiku.o : haiku.h io.o : loggers.h linux.o : linux.h logfile.o : block.h loggers.o : block.h loggers.h rational.o : rational.h rescuebook.o : loggers.h -main.o : arg_parser.h rational.h linux.h loggers.h main_common.cc +main.o : arg_parser.h rational.h loggers.h main_common.cc ddrescuelog.o : Makefile arg_parser.h block.h ddrescue.h main_common.cc diff --git a/ddrescue.h b/ddrescue.h index 59d3111..d494913 100644 --- a/ddrescue.h +++ b/ddrescue.h @@ -264,3 +264,19 @@ const char * format_time( long t ); bool interrupted(); void set_signals(); int signaled_exit(); + + +// Default implementations +#if !defined __HAIKU__ +inline long long device_size( const int fd ) { + { + return lseek( fd, 0, SEEK_END ); + } +#else +long long device_size( const int fd ); +#endif +#if !defined USE_LINUX && !defined __HAIKU__ +inline const char * device_id( const int ) { return 0; } +#else +const char * device_id( const int ); +#endif diff --git a/haiku.cc b/haiku.cc new file mode 100644 index 0000000..a78e0da --- /dev/null +++ b/haiku.cc @@ -0,0 +1,63 @@ +/* GNU ddrescue - Data recovery tool + Copyright (C) 2014 Antonio Diaz Diaz. + + 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 2 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 . +*/ + +#include "haiku.h" + +#ifdef __HAIKU__ +#include +#include +#include +#include + + +void sanitize_string( std::string & str ) + { + for( unsigned i = str.size(); i > 0; --i ) // remove non-printable chars + { + const unsigned char ch = str[i-1]; + if( std::isspace( ch ) ) str[i-1] = ' '; + else if( ch < 32 || ch > 126 ) str.erase( i - 1, 1 ); + } + for( unsigned i = str.size(); i > 0; --i ) // remove duplicate spaces + if( str[i-1] == ' ' && ( i <= 1 || i >= str.size() || str[i-2] == ' ' ) ) + str.erase( i - 1, 1 ); + } + +const char * device_id( const int fd ) + { + static std::string id_str; + char id[256]; + + if( ioctl( fd, B_GET_DEVICE_NAME, &id, sizeof(id) ) != 0 ) return 0; + id_str = (const char *)id; + // XXX: is it needed anyway? + sanitize_string( id_str ); + return id_str.c_str(); + } + +off_t device_size( const int fd ) + { + off_t size; + device_geometry geom; + + if( ioctl( fd, B_GET_GEOMETRY, &geom, sizeof(geom) ) != 0 ) return 0; + size = (off_t)geom.bytes_per_sector * geom.sectors_per_track; + size *= (off_t)geom.cylinder_count * geom.head_count; + return size; + } + +#endif diff --git a/haiku.h b/haiku.h new file mode 100644 index 0000000..00033fd --- /dev/null +++ b/haiku.h @@ -0,0 +1,19 @@ +/* GNU ddrescue - Data recovery tool + Copyright (C) 2014 Antonio Diaz Diaz. + + 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 2 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 . +*/ + +const char * device_id( const int fd ); +long long device_size( const int fd ); diff --git a/linux.cc b/linux.cc index c1021b5..89b3727 100644 --- a/linux.cc +++ b/linux.cc @@ -53,8 +53,4 @@ const char * device_id( const int fd ) return 0; } -#else - -const char * device_id( const int ) { return 0; } - #endif diff --git a/main.cc b/main.cc index 2f5fb8b..f93abcb 100644 --- a/main.cc +++ b/main.cc @@ -296,7 +296,7 @@ int do_generate( const long long offset, Domain & domain, const int ides = open( iname, O_RDONLY | O_BINARY ); if( ides < 0 ) { show_error( "Can't open input file", errno ); return 1; } - const long long isize = lseek( ides, 0, SEEK_END ); + const long long isize = device_size( ides ); if( isize < 0 ) { show_error( "Input file is not seekable." ); return 1; } @@ -337,7 +337,7 @@ const char * device_id_or_size( const int fd ) const char * p = device_id( fd ); if( !p ) { - const long long size = lseek( fd, 0, SEEK_END ); + const long long size = device_size( fd ); snprintf( buf, sizeof buf, "%lld", size ); p = buf; } @@ -395,7 +395,7 @@ int do_rescue( const long long offset, Domain & domain, const int ides = open( iname, O_RDONLY | rb_opts.o_direct | O_BINARY ); if( ides < 0 ) { show_error( "Can't open input file", errno ); return 1; } - long long isize = lseek( ides, 0, SEEK_END ); + long long isize = device_size( ides ); if( isize < 0 ) { show_error( "Input file is not seekable." ); return 1; } if( test_domain ) @@ -578,7 +578,7 @@ bool Rescuebook::reopen_infile() ides_ = open( iname_, O_RDONLY | o_direct | O_BINARY ); if( ides_ < 0 ) { final_msg( "Can't reopen input file", errno ); return false; } - const long long isize = lseek( ides_, 0, SEEK_END ); + const long long isize = device_size( ides_ ); if( isize < 0 ) { final_msg( "Input file has become not seekable", errno ); return false; } return true; -- 1.8.3.4