Logo Search packages:      
Sourcecode: condor version File versions  Download package

test_log_reader_state.cpp

/***************************************************************
 *
 * Copyright (C) 1990-2008, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "read_user_log.h"
#include "read_user_log_state.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "condor_distribution.h"
#include "MyString.h"
#include "subsystem_info.h"
#include "simple_arg.h"
#include <stdio.h>

static const char *     VERSION = "0.1.0";

DECL_SUBSYSTEM( "TEST_LOG_READER_STATE", SUBSYSTEM_TYPE_TOOL );

enum Verbosity
{
      VERB_NONE = 0,
      VERB_ERROR,
      VERB_WARNING,
      VERB_ALL
};
enum Command
{
      CMD_NONE,
      CMD_DUMP,
      CMD_LIST,
      CMD_VERIFY
};
enum Field
{
      FIELD_NONE,
      FIELD_SIGNATURE,
      FIELD_VERSION,
      FIELD_UPDATE_TIME,
      FIELD_BASE_PATH,
      FIELD_CUR_PATH,
      FIELD_UNIQ_ID,
      FIELD_SEQUENCE,
      FIELD_MAX_ROTATION,
      FIELD_ROTATION,
      FIELD_OFFSET,
      FIELD_GLOBAL_POSITION,
      FIELD_GLOBAL_RECORD_NUM,
      FIELD_INODE,
      FIELD_CTIME,
      FIELD_SIZE,
      FIELD_ALL,
};
enum DataType
{
      TYPE_STRING,
      TYPE_INT,
      TYPE_FSIZE,
      TYPE_INODE,
      TYPE_TIME,
      TYPE_NONE,
};

struct FieldData
{
      Field        m_field;
      DataType     m_type;
      int                m_max_values;
      char        *m_name;
};
static const FieldData fieldList[] =
{
      { FIELD_SIGNATURE,                  TYPE_STRING,      1,  "signature" },
      { FIELD_VERSION,              TYPE_INT,         2,  "version" },
      { FIELD_UPDATE_TIME,          TYPE_TIME,        2,  "update-time" },
      { FIELD_BASE_PATH,                  TYPE_STRING,      1,  "base-path" },
      { FIELD_CUR_PATH,             TYPE_STRING,      1,  "path" },
      { FIELD_UNIQ_ID,              TYPE_STRING,      1,  "uniq" },
      { FIELD_SEQUENCE,             TYPE_INT,         2,  "sequence" },
      { FIELD_MAX_ROTATION,         TYPE_INT,         2,  "max-rotation" },
      { FIELD_ROTATION,             TYPE_INT,         2,  "rotation" },
      { FIELD_OFFSET,                     TYPE_FSIZE,       2,  "offset" },
      { FIELD_GLOBAL_POSITION,      TYPE_FSIZE,       2,  "global-position" },
      { FIELD_GLOBAL_RECORD_NUM,    TYPE_FSIZE,       2,  "global-record" },
      { FIELD_INODE,                      TYPE_INODE,       1,  "inode" },
      { FIELD_CTIME,                      TYPE_TIME,        2,  "ctime" },
      { FIELD_SIZE,                       TYPE_FSIZE,       2,  "size" },
      { FIELD_ALL,                        TYPE_NONE,        0,  "all" },
      { FIELD_NONE,                       TYPE_NONE,        -1, NULL, },
};

union IntVal { filesize_t asFsize; int asInt; time_t asTime; };
struct Value
{
      struct { IntVal minVal; IntVal maxVal; } asRange;
      IntVal                   asInt;
      StatStructInode    asInode;
      const char        *asStr;
};

class Options
{
public:
      Options( void );
      ~Options( void ) { };


      int handleOpt( SimpleArg &arg, int & );
      int handleFixed( SimpleArg &arg, int & );

      const char *getFile( void ) const { return m_file; };
      Command getCommand( void ) const { return m_command; };
      const FieldData *getField( void ) const { return m_field; };
      Value getValue( void ) const { return m_value; };
      bool isValueRange( void ) const { return m_value_is_range; };
      int getVerbose( void ) const { return m_verbose; };
      bool getNumeric( void ) const { return m_numeric; };
      const char *getUsage( void ) const { return m_usage; };
      void dumpFieldList( void ) const;
      const FieldData *lookupField( Field field ) const;
      bool isValueOk( void ) const { return m_num_values >= 1; };
      bool needStateFile( void ) const { return m_command != CMD_LIST; };

private:
      enum { ST_CMD, ST_FILE, ST_FIELD, ST_VALUES, ST_NONE } m_state;
      const char        *m_file;
      Command                  m_command;
      const FieldData   *m_field;
      Value              m_value;
      bool               m_value_is_range;
      int                      m_num_values;
      int                      m_verbose;
      bool               m_numeric;
      const char        *m_usage;

      bool lookupCommand( const SimpleArg & );
      const FieldData *lookupField( const char *arg ) const;
      const FieldData *lookupField( const SimpleArg &arg ) const;
      bool parseValue( const SimpleArg &arg );
};

int
CheckArgs(int argc, const char **argv, Options &opts);
int
ReadState(const Options &opts, ReadUserLog::FileState &state );
int
DumpState(const Options &opts, const ReadUserLog::FileState &state,
              const FieldData *wdata = NULL );
int
VerifyState(const Options &opts, const ReadUserLog::FileState &state );

const char *timestr( struct tm &tm, char *buf = NULL, int bufsize = 0 );
const char *timestr( time_t t, char *buf = NULL, int bufsize = 0 );
const char *chomptime( char *buf );

// Simple term signal handler
static bool global_done = false;
void handle_sig(int sig)
{
      (void) sig;
      printf( "Got signal; shutting down\n" );
      global_done = true;
}

int
main(int argc, const char **argv)
{
      DebugFlags = D_ALWAYS;

            // initialize to read from config file
      myDistro->Init( argc, argv );
      config();

            // Set up the dprintf stuff...
      dprintf_config("TEST_LOG_READER_STATE");

      Options     opts;
      if ( CheckArgs( argc, argv, opts ) < 0 ) {
            fprintf( stderr, "CheckArgs() failed\n" );
            exit( 1 );
      }

      ReadUserLog::FileState  state;
      if ( opts.needStateFile() && ( ReadState( opts, state ) < 0 )  ) {
            fprintf( stderr, "ReadState() failed\n" );
            exit( 1 );
      }

      int   status = 0;
      switch( opts.getCommand() )
      {
      case CMD_NONE:
            status = -1;
            break;
      case CMD_LIST:
            opts.dumpFieldList( );
            break;
      case CMD_DUMP:
            status = DumpState( opts, state );
            break;
      case CMD_VERIFY:
            status = VerifyState( opts, state );
            break;
      }

      if ( status == 0 ) {
            exit( 0 );
      } else {
            exit( 2 );
      }
}

int
CheckArgs(int argc, const char **argv, Options &opts)
{
      int         status = 0;

      for ( int argno = 1;  argno < argc && status >= 0;  argno++ ) {
            SimpleArg   arg( argv, argc, argno );

            if ( arg.Error() ) {
                  fprintf( stderr, "Failed parsing '%s'\n", arg.Arg() );
                  status = -1;
            }

            if ( status > 0 ) {
                  fprintf( stderr,
                               "Warning: ignoring parameter %s\n"
                               "  use -h for help\n",
                               arg.Arg() );
            }
            else if ( arg.ArgIsOpt() ) {
                  status = opts.handleOpt( arg, argno );
            }
            else {
                  status = opts.handleFixed( arg, argno );
            }
      }

      if ( ( opts.needStateFile() ) && ( NULL == opts.getFile() ) ) {
            fprintf( stderr,
                         "No state file specified\n"
                         "  use -h for help\n" );
            status = -1;
      }
      else if ( CMD_NONE == opts.getCommand() ) {
            fprintf( stderr,
                         "No command specified\n"
                         "  use -h for help\n" );
            status = -1;
      }
      else if ( CMD_VERIFY == opts.getCommand() ) {
            if ( NULL == opts.getField() ||
                   FIELD_NONE == opts.getField()->m_field ) {
                  fprintf( stderr,
                               "Verify: no field name specified\n"
                               "  use -h for help\n" );
                  status = -1;
            }
            else if ( ! opts.isValueOk() ) {
                  fprintf( stderr,
                               "Verify: no value (or range) specified\n"
                               "  use -h for help\n" );
                  status = -1;
            }

      }
      return status;
}

int
ReadState(const Options &opts, ReadUserLog::FileState &state )
{

      // Create & initialize the state
      ReadUserLog::InitFileState( state );

      int   fd = safe_open_wrapper( opts.getFile(), O_RDONLY, 0 );
      if ( fd < 0 ) {
            fprintf( stderr, "Failed to read state file %s\n", opts.getFile() );
            return -1;
      }

      if ( read( fd, state.buf, state.size ) != state.size ) {
            fprintf( stderr, "Failed reading state file %s\n", opts.getFile() );
            close( fd );
            return -1;
      }
      close( fd );

      return 0;
}


int
DumpState( const Options &opts,
               const ReadUserLog::FileState &state,
               const FieldData *wdata )
{
      ReadUserLogState  rstate( state, 60 );
      const ReadUserLogState::FileState   *istate =
            ReadUserLogState::GetFileStateConst( state );

      if ( NULL == wdata ) {
            wdata = opts.getField( );
      }

      switch( wdata->m_field )
      {
      case FIELD_NONE:
            return -1;
            break;

      case FIELD_SIGNATURE:
            printf( "  %s: '%s'\n", wdata->m_name, istate->m_signature );
            break;

      case FIELD_VERSION:
            printf( "  %s: %d\n", wdata->m_name, istate->m_version );
            break;

      case FIELD_UPDATE_TIME:
            if ( opts.getNumeric() ) {
                  printf( "  %s: %lu\n", wdata->m_name,
                              (long unsigned) istate->m_update_time );
            } else {
                  printf( "  %s: '%s'\n", wdata->m_name,
                              timestr(istate->m_update_time) );
            }
            break;

      case FIELD_BASE_PATH:
            printf( "  %s: '%s'\n", wdata->m_name, istate->m_base_path );
            break;

      case FIELD_CUR_PATH:
            printf( "  %s: '%s'\n", wdata->m_name, rstate.CurPath(state) );
            break;

      case FIELD_UNIQ_ID:
            printf( "  %s: '%s'\n", wdata->m_name, istate->m_uniq_id );
            break;

      case FIELD_SEQUENCE:
            printf( "  %s: %d\n", wdata->m_name, istate->m_sequence );
            break;

      case FIELD_MAX_ROTATION:
            printf( "  %s: %d\n", wdata->m_name, istate->m_max_rotations );
            break;

      case FIELD_ROTATION:
            printf( "  %s: %d\n", wdata->m_name, istate->m_rotation );
            break;

      case FIELD_OFFSET:
            printf( "  %s: " FILESIZE_T_FORMAT "\n",
                        wdata->m_name, istate->m_offset.asint );
            break;

      case FIELD_GLOBAL_POSITION:
            printf( "  %s: " FILESIZE_T_FORMAT "\n",
                        wdata->m_name, istate->m_log_position.asint );
            break;

      case FIELD_GLOBAL_RECORD_NUM:
            printf( "  %s: " FILESIZE_T_FORMAT "\n",
                        wdata->m_name, istate->m_log_record.asint );
            break;

      case FIELD_INODE:
            printf( "  %s: %lu\n", wdata->m_name,
                        (long unsigned) istate->m_inode );
            break;

      case FIELD_CTIME:
            if ( opts.getNumeric() ) {
                  printf( "  %s: %lu\n", wdata->m_name,
                              (long unsigned) istate->m_ctime );
            } else {
                  printf( "  %s: '%s'\n", wdata->m_name,
                              timestr(istate->m_ctime) );
            }
            break;

      case FIELD_SIZE:
            printf( "  %s: " FILESIZE_T_FORMAT "\n",
                        wdata->m_name, istate->m_size.asint );
            break;

      case FIELD_ALL:
            DumpState( opts, state, opts.lookupField(FIELD_SIGNATURE) );
            DumpState( opts, state, opts.lookupField(FIELD_VERSION) );
            DumpState( opts, state, opts.lookupField(FIELD_UPDATE_TIME) );
            DumpState( opts, state, opts.lookupField(FIELD_BASE_PATH) );
            DumpState( opts, state, opts.lookupField(FIELD_CUR_PATH) );
            DumpState( opts, state, opts.lookupField(FIELD_UNIQ_ID) );
            DumpState( opts, state, opts.lookupField(FIELD_SEQUENCE) );
            DumpState( opts, state, opts.lookupField(FIELD_MAX_ROTATION) );
            DumpState( opts, state, opts.lookupField(FIELD_ROTATION) );
            DumpState( opts, state, opts.lookupField(FIELD_OFFSET) );
            DumpState( opts, state, opts.lookupField(FIELD_GLOBAL_POSITION) );
            DumpState( opts, state, opts.lookupField(FIELD_GLOBAL_RECORD_NUM) );
            DumpState( opts, state, opts.lookupField(FIELD_INODE) );
            DumpState( opts, state, opts.lookupField(FIELD_CTIME) );
            DumpState( opts, state, opts.lookupField(FIELD_SIZE) );
            break;

      default:
            return -1;
      }
      return 0;
}

bool
CompareStr( const Options &opts, const char *val )
{
      bool  ok;

      ok = ( strcasecmp( val, opts.getValue().asStr ) == 0 );
      if ( !ok && opts.getVerbose() ) {
            printf( "  %s: '%s' != '%s'\n",
                        opts.getField()->m_name, val, opts.getValue().asStr );
      }
      return ok;
}

bool
CompareInt( const Options &opts, int val )
{
      bool  ok;

      if ( opts.isValueRange() ) {
            ok = (  ( val >= opts.getValue().asRange.minVal.asInt ) &&
                        ( val <= opts.getValue().asRange.maxVal.asInt )  );

            if ( !ok && opts.getVerbose() ) {
                  printf( "  %s: %d not in %d - %d\n",
                              opts.getField()->m_name,
                              val,
                              opts.getValue().asRange.minVal.asInt,
                              opts.getValue().asRange.maxVal.asInt );
            }
      }
      else {
            ok = ( val == opts.getValue().asInt.asInt );
            if ( !ok && opts.getVerbose() ) {
                  printf( "  %s: %d != %d\n",
                              opts.getField()->m_name,
                              val,
                              opts.getValue().asInt.asInt );
            }
      }

      return ok;
}

bool
CompareFsize( const Options &opts, filesize_t val )
{
      bool  ok;

      if ( opts.isValueRange() ) {
            ok = (  ( val >= opts.getValue().asRange.minVal.asFsize ) &&
                        ( val <= opts.getValue().asRange.maxVal.asFsize )  );

            if ( !ok && opts.getVerbose() ) {
                  printf( "  %s: " FILESIZE_T_FORMAT
                              "not in " FILESIZE_T_FORMAT " - " FILESIZE_T_FORMAT "\n",
                              opts.getField()->m_name,
                              val,
                              opts.getValue().asRange.minVal.asFsize,
                              opts.getValue().asRange.maxVal.asFsize );
            }
      }
      else {
            ok = ( val == opts.getValue().asInt.asInt );
            if ( !ok && opts.getVerbose() ) {
                  printf( "  %s: " FILESIZE_T_FORMAT " != " FILESIZE_T_FORMAT "\n",
                              opts.getField()->m_name,
                              val,
                              opts.getValue().asInt.asFsize );
            }
      }

      return ok;
}

bool
CompareTime( const Options &opts, time_t val )
{
      bool  ok;
      char  b1[64], b2[64], b3[64];

      if ( opts.isValueRange() ) {
            ok = (  ( val >= opts.getValue().asRange.minVal.asTime ) &&
                        ( val <= opts.getValue().asRange.maxVal.asTime )  );

            if ( !ok && opts.getVerbose() ) {
                  if ( opts.getNumeric() ) {
                        printf( "  %s: %lu not in %lu - %lu\n",
                                    opts.getField()->m_name,
                                    (unsigned long)val,
                                    (unsigned long)opts.getValue().asRange.minVal.asTime,
                                    (unsigned long)opts.getValue().asRange.maxVal.asTime );
                  }
                  else {
                        printf( "  %s: %s not in %s - %s\n",
                                    opts.getField()->m_name,
                                    timestr( val, b1, sizeof(b1) ),
                                    timestr( opts.getValue().asRange.minVal.asTime,
                                                 b2, sizeof(b2) ),
                                    timestr( opts.getValue().asRange.maxVal.asTime,
                                                 b3, sizeof(b3) ) );
                  }
            }
      }
      else {
            ok = ( val == opts.getValue().asInt.asTime );
            if ( !ok && opts.getVerbose() ) {
                  if ( opts.getNumeric() ) {
                        printf( "  %s: %lu != %lu\n",
                                    opts.getField()->m_name,
                                    (unsigned long) val,
                                    (unsigned long) opts.getValue().asInt.asTime );
                  }
                  else {
                        printf( "  %s: %s != %s\n",
                                    opts.getField()->m_name,
                                    timestr( val, b1, sizeof(b1) ),
                                    timestr( opts.getValue().asRange.minVal.asTime,
                                                 b2, sizeof(b2) ) );
                  }
            }
      }

      return ok;
}

bool
CompareInode( const Options &opts, StatStructInode val )
{
      bool  ok;

      ok = val == opts.getValue().asInode;
      if ( !ok && opts.getVerbose() ) {
                  printf( "  %s: %lu != %lu\n",
                              opts.getField()->m_name,
                              (unsigned long) val,
                              (unsigned long) opts.getValue().asInode );
      }

      return ok;
}

int
VerifyState(const Options &opts, const ReadUserLog::FileState &state )
{
      ReadUserLogState  rstate( state, 60 );
      const ReadUserLogState::FileState   *istate =
            ReadUserLogState::GetFileStateConst( state );

      const FieldData   *wdata = opts.getField( );
      if ( wdata == NULL ) {
            fprintf( stderr, "Verify: no field!\n" );
            return -1;
      }

      bool  ok;
      switch( wdata->m_field )
      {
      case FIELD_SIGNATURE:
            ok = CompareStr( opts, istate->m_signature );
            break;

      case FIELD_VERSION:
            ok = CompareInt( opts, istate->m_version );
            break;

      case FIELD_UPDATE_TIME:
            ok = CompareTime( opts, istate->m_update_time );
            break;

      case FIELD_BASE_PATH:
            ok = CompareStr( opts, istate->m_base_path );
            break;

      case FIELD_CUR_PATH:
            ok = CompareStr( opts, rstate.CurPath(state) );
            break;

      case FIELD_UNIQ_ID:
            ok = CompareStr( opts, istate->m_uniq_id );
            break;

      case FIELD_SEQUENCE:
            ok = CompareInt( opts, istate->m_sequence );
            break;

      case FIELD_MAX_ROTATION:
            ok = CompareInt( opts, istate->m_max_rotations );
            break;

      case FIELD_ROTATION:
            ok = CompareInt( opts, istate->m_rotation );
            break;

      case FIELD_OFFSET:
            ok = CompareFsize( opts, istate->m_offset.asint );
            break;

      case FIELD_GLOBAL_POSITION:
            ok = CompareFsize( opts, istate->m_log_position.asint );
            break;

      case FIELD_GLOBAL_RECORD_NUM:
            ok = CompareFsize( opts, istate->m_log_record.asint );
            break;

      case FIELD_INODE:
            ok = CompareInode( opts, istate->m_inode );
            break;

      case FIELD_CTIME:
            ok = CompareTime( opts, istate->m_ctime );
            break;

      case FIELD_SIZE:
            ok = CompareFsize( opts, istate->m_size.asint );
            break;

      default:
            return -1;
      }
      return ok ? 0 : 1;
}

const char *
timestr( time_t t, char *buf, int bufsize )
{
      static char sbuf[64];
      if ( NULL == buf ) {
            buf = sbuf;
            bufsize = sizeof(sbuf);
      }

      strncpy( buf, ctime(&t), bufsize );
      return chomptime( buf );
}

const char *
timestr( struct tm &t, char *buf, int bufsize )
{
      static char sbuf[64];
      if ( NULL == buf ) {
            buf = sbuf;
            bufsize = sizeof(sbuf);
      }

      strncpy( buf, asctime( &t ), bufsize );
      buf[bufsize-1] = '\0';
      return chomptime( buf );
}

const char *
chomptime( char *buf )
{
      int len = strlen( buf );
      while ( len && isspace( buf[len-1] ) ) {
            buf[len-1] = '\0';
            len--;
      }
      return buf;
}

Options::Options( void )
{
      m_state = ST_CMD;
      m_file = NULL;
      m_command = CMD_NONE;
      m_field = NULL;
      memset( &m_value, 0, sizeof(m_value) );
      m_value_is_range = false;
      m_num_values = 0;
      m_verbose = VERB_NONE;
      m_numeric = false;
      m_usage =
            "Usage: test_log_reader_state "
            "[options] <command> [filename [field-name [value/min [max-value]]]]\n"
            "  commands: dump verify list\n"
            "    dump/any: dump [what]\n"
            "    verify/numeric: what min max\n"
            "    verify/string:  what [value]\n"
            "    list (list names of things)\n"
            "  --numeric|-n: dump times as numeric\n"
            "  --usage|--help|-h: print this message and exit\n"
            "  -v: Increase verbosity level by 1\n"
            "  --verbosity <number>: set verbosity level (default is 1)\n"
            "  --version: print the version number and compile date\n"
            "  <filename>: the persistent file to read\n";
}

int
Options::handleOpt( SimpleArg &arg, int &argno )
{
      if ( arg.Match('n', "numeric") ) {
            m_numeric = true;

      } else if ( arg.Match('d', "debug") ) {
            if ( arg.hasOpt() ) {
                  set_debug_flags( const_cast<char *>(arg.getOpt()) );
                  argno = arg.ConsumeOpt( );
            } else {
                  fprintf(stderr, "Value needed for '%s'\n", arg.Arg() );
                  printf("%s", m_usage);
                  return -1;
            }

      } else if ( arg.Match('v') ) {
            m_verbose++;

      } else if ( arg.Match("verbosity") ) {
            if ( !arg.getOpt( m_verbose ) ) {
                  fprintf(stderr, "Value needed for '%s'\n", arg.Arg() );
                  printf("%s", m_usage);
                  return -1;
            }

      } else if ( arg.Match("version") ) {
            printf("test_log_reader_state: %s, %s\n", VERSION, __DATE__);
            return 1;
      }
      else {
            fprintf(stderr, "Unrecognized argument: '%s'\n", arg.Arg() );
            printf("%s", m_usage);
            return -1;
      }
      return 0;
}

int
Options::handleFixed( SimpleArg &arg, int & /*argno*/ )
{
      if ( ST_CMD == m_state ) {
            if ( !lookupCommand( arg ) ) {
                  fprintf(stderr, "Invalid command '%s'\n", arg.Arg() );
                  printf("%s", m_usage);
                  m_state = ST_NONE;
                  return -1;
            }
            if ( CMD_LIST == m_command ) {
                  m_state = ST_NONE;
                  return 1;
            }
            else if ( CMD_DUMP == m_command ) {
                  m_field = lookupField( "all" );
                  if ( NULL == m_field ) {
                        assert( 0 );
                  }
            }
            m_state = ST_FILE;
      }
      else if ( ST_FILE == m_state ) {
            m_file = arg.Arg();
            m_state = ST_FIELD;
      }
      else if ( ST_FIELD == m_state ) {
            m_field = lookupField( arg );
            if ( NULL == m_field ) {
                  fprintf(stderr, "Invalid field '%s'\n", arg.Arg() );
                  printf("%s", m_usage);
                  m_state = ST_NONE;
                  return -1;
            }

            if ( 0 == m_field->m_max_values ) {
                  m_state = ST_NONE;
                  return 1;
            }
            m_state = ST_VALUES;
      }
      else if (  ( ST_VALUES == m_state ) &&
                     ( m_field ) &&
                     ( m_num_values < m_field->m_max_values ) ) {
            if ( !parseValue( arg ) ) {
                  fprintf(stderr, "Invalid value for %s: '%s'\n",
                              m_field->m_name, arg.Arg() );
                  return -1;
            }
            m_num_values++;
      }
      else {
            fprintf(stderr, "Unexpected arg '%s'\n", arg.Arg() );
            return -1;
      }

      return 0;
}

bool
Options::lookupCommand( const SimpleArg &arg )
{
      const char  *s = arg.Arg( );
      char        c = '\0';

      if ( 1 == strlen(s) ) {
            c = s[0];
      }
      if ( 'd' == c  ||  (0 == strcasecmp( s, "dump" )) ) {
            m_command = CMD_DUMP;
            return true;
      }
      else if ( 'v' == c  ||  (0 == strcasecmp( s, "verify" )) ) {
            m_command = CMD_VERIFY;
            return true;
      }
      else if ( 'l' == c  ||  (0 == strcasecmp( s, "list" )) ) {
            m_command = CMD_LIST;
            return true;
      }
      return false;
}

void
Options::dumpFieldList( void ) const
{
      const FieldData   *field = &fieldList[0];
      for( field = &fieldList[0]; field->m_field != FIELD_NONE; field++ ) {
            printf( "  %s\n", field->m_name );
      }
}

const FieldData *
Options::lookupField( Field arg ) const
{
      const FieldData   *field;
      for( field = &fieldList[0]; field->m_field != FIELD_NONE; field++ ) {
            if ( field->m_field == arg ) {
                  return field;
            }
      }
      return NULL;
}

const FieldData *
Options::lookupField( const char *arg ) const
{
      const FieldData   *field;
      for( field = &fieldList[0]; field->m_field != FIELD_NONE; field++ ) {
            if ( 0 == strcasecmp( arg, field->m_name ) ) {
                  return field;
            }
      }
      return NULL;
}

const FieldData *
Options::lookupField( const SimpleArg &arg ) const
{
      return lookupField( arg.Arg() );
}

bool
Options::parseValue( const SimpleArg &arg )
{
      const char *s = arg.Arg( );
      if ( TYPE_STRING == m_field->m_type ) {
            m_value.asStr = s;
            return true;
      }
      if ( ( TYPE_INT == m_field->m_type ) && ( isdigit(*s) ) ) {
            int         i = atoi(s);
            if ( 0 == m_num_values ) {
                  m_value.asInt.asInt = i;
                  m_value.asRange.minVal.asInt = i;
                  m_value.asRange.maxVal.asInt = i;
            }
            else {
                  m_value.asRange.maxVal.asInt = i;
                  m_value_is_range = true;
            }
            return true;
      }
      if ( ( TYPE_FSIZE == m_field->m_type ) && ( isdigit(*s) ) ) {
            filesize_t        i = (filesize_t) atol(s);
            if ( 0 == m_num_values ) {
                  m_value.asInt.asFsize = i;
                  m_value.asRange.minVal.asFsize = i;
                  m_value.asRange.maxVal.asFsize = i;
            }
            else {
                  m_value.asRange.maxVal.asFsize = i;
                  m_value_is_range = true;
            }
            return true;
      }
      if ( ( TYPE_TIME == m_field->m_type ) && ( isdigit(*s) ) ) {
            time_t            i = (time_t) atol(s);
            if ( 0 == m_num_values ) {
                  m_value.asInt.asTime = i;
                  m_value.asRange.minVal.asTime = i;
                  m_value.asRange.maxVal.asTime = i;
            }
            else {
                  m_value.asRange.maxVal.asTime = i;
                  m_value_is_range = true;
            }
            return true;
      }
      if ( ( TYPE_INODE == m_field->m_type ) && ( isdigit(*s) ) ) {
            m_value.asInode = (StatStructInode) atol(s);
            return true;
      }
      return false;
}

Generated by  Doxygen 1.6.0   Back to index