/*  Common code for Zcmp and Zdiff
    Copyright (C) 2010, 2011, 2012, 2013 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 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 <http://www.gnu.org/licenses/>.
*/

#ifdef O_BINARY
const int o_binary = O_BINARY;
#else
const int o_binary = 0;
#endif

struct { const char * from; const char * to; } const known_extensions[] = {
  { ".bz2",  ""     },
  { ".tbz",  ".tar" },
  { ".tbz2", ".tar" },
  { ".gz",   ""     },
  { ".tgz",  ".tar" },
  { ".lz",   ""     },
  { ".tlz",  ".tar" },
  { ".xz",   ""     },
  { ".txz",  ".tar" },
  { 0,       0      } };


int open_instream( const std::string & input_filename )
  {
  int infd = open( input_filename.c_str(), O_RDONLY | o_binary );
  if( infd < 0 )
    show_error2( "Can't open input file", input_filename.c_str() );
  return infd;
  }


int open_other_instream( std::string & name )
  {
  for( int i = 0; known_extensions[i].from; ++i )
    {					// search uncompressed version
    const std::string from( known_extensions[i].from );
    if( name.size() > from.size() &&
        name.compare( name.size() - from.size(), from.size(), from ) == 0 )
      {
      name.resize( name.size() - from.size() );
      name += known_extensions[i].to;
      return open( name.c_str(), O_RDONLY | o_binary );
      }
    }
  for( int i = 0; i < num_formats; ++i )
    {					// search compressed version
    const std::string s( name + simple_extensions[format_order[i]] );
    const int infd = open( s.c_str(), O_RDONLY | o_binary );
    if( infd >= 0 ) { name = s; return infd; }
    }
  return -1;
  }


void parse_format_types( const std::string & arg, int format_types[2] )
  {
  const unsigned i = std::min( arg.find( ',' ), arg.size() );
  if( i > 0 ) format_types[0] = parse_format_type( arg.substr( 0, i ) );
  else format_types[0] = -1;
  if( i + 1 < arg.size() ) format_types[1] =
    parse_format_type( arg.substr( i + 1 ) );
  else format_types[1] = -1;
  }


bool check_identical( const char * const name1, const char * const name2 )
  {
  if( !std::strcmp( name1, name2 ) ) return true;
  struct stat stat1, stat2;
  if( stat( name1, &stat1 ) || stat( name2, &stat2 ) ) return false;
  return ( stat1.st_ino == stat2.st_ino && stat1.st_dev == stat2.st_dev );
  }
