/*
 * tools/lvmchange.c
 *
 * Copyright (C) 1997 - 2000  Heinz Mauelshagen, Sistina Software
 *
 * March-May 1997
 * June,August 1998
 * February,October 1999
 * February 2000
 * February 2001
 *
 * LVM 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, or (at your option)
 * any later version.
 * 
 * LVM 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 LVM; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA. 
 *
 */

/*
 * Changelog
 *
 *    12/06/1998 - enhanced checking numbers in option arguments
 *    04/09/1998 - corrected some messages
 *    06/02/1999 - fixed lvm_check_number() usage
 *    11/02/1999 - removed obsolete -r support (read ahead sectors)
 *                 including usage of lvm_check_number()
 *    21/02/1999 - removed LVM_LOCK and LVM_UNLOCK
 *    06/10/1999 - implemented support for long options
 *    15/02/2000 - use lvm_error()
 *    23/01/2001 - added call to lvm_init (JT)
 *    07/02/2001 - added i option to display the io protocol version
 *
 */

#include <lvm_user.h>

char *cmd = NULL;

#ifdef DEBUG
int opt_d = 0;
#endif

int main ( int argc, char **argv) {
   int c = 0;
   int c1 = 0;
   int lvm = -1;
   int opt_f = 0;
   int opt_i = 0;
   int opt_R = 0;
   int opt_v = 0;
   int ret = 0;
#ifdef DEBUG
   char *options = "dfh?iRv";
#else
   char *options = "fh?iRv";
#endif
   struct option long_options[] = {
#ifdef DEBUG
      { "debug",      no_argument,       NULL, 'd'},
#endif
      { "force",      no_argument,       NULL, 'f'},
      { "help",       no_argument,       NULL, 'h'},
      { "iop_version",no_argument,       NULL, 'i'},
      { "reset",      no_argument,       NULL, 'R'},
      { "verbose",    no_argument,       NULL, 'v'},
      { NULL, 0, NULL, 0}
   };

   /* lvm_init(argc, argv); */
   cmd = basename ( argv[0]);

   SUSER_CHECK;

   while ( ( c = getopt_long ( argc, argv, options,
                               long_options, NULL)) != EOF) {
      switch ( c) {
#ifdef DEBUG
         case 'd':
            if ( opt_d > 0) {
               fprintf ( stderr, "%s -- d option already given\n\n", cmd);
               return LVM_EINVALID_CMD_LINE;
            }
            opt_d++;
            break;
#endif

         case 'f':
            if ( opt_f > 0) {
               fprintf ( stderr, "%s -- f option already given\n\n", cmd);
               return LVM_EINVALID_CMD_LINE;
            }
            opt_f++;
            break;

         case 'i':
            if ( opt_i > 0) {
               fprintf ( stderr, "%s -- i option already given\n\n", cmd);
               return LVM_EINVALID_CMD_LINE;
            }
            opt_i++;
            break;


         case 'h':
         case '?':
            printf ( "\n%s (IOP %d)\n\n%s -- Logical Volume Manager Change\n\n"
                     "Synopsis:\n"
                     "---------\n\n"
                     "%s\n"
#ifdef DEBUG
                     "\t[-d/--debug]\n"
#endif
                     "\t[-f/--force]\n"
                     "\t[-h/-?/--help]\n"
                     "\t[-i/-?/--iop_version]\n"
                     "\t[-R/--reset]\n"
                     "\t[-v/--verbose]\n\n",
                     lvm_version, LVM_LIB_IOP_VERSION,  cmd, cmd);
            return 0;
            break;

         case 'R':
            if ( opt_R > 0) {
               fprintf ( stderr, "%s -- R option already given\n\n", cmd);
               return LVM_EINVALID_CMD_LINE;
            }
            opt_R++;
            break;

         case 'v':
            if ( opt_v > 0) {
               fprintf ( stderr, "%s -- v option already given\n\n", cmd);
               return LVM_EINVALID_CMD_LINE;
            }
            opt_v++;
            break;

         default:
            fprintf ( stderr, "%s -- invalid command line option \"%c\"\n\n",
                      cmd, c);
            return LVM_EINVALID_CMD_LINE;
      }
   }
  
   CMD_MINUS_CHK;

   if (opt_i && opt_R) {
      fprintf ( stderr, "%s -- option i and R are exclusive\n\n", cmd);
      return LVM_EINVALID_CMD_LINE;
   }

   if ( opt_i > 0) {
      printf ( "%s -- IO protocol version: %d\n\n", cmd, lvm_get_iop_version());
      return 0;
   }

   if ( opt_R == 0) {
      fprintf ( stderr, "%s -- please give the R option\n\n", cmd);
      return LVM_EINVALID_CMD_LINE;
   }

   if ( optind < argc) {
      fprintf ( stderr, "%s -- error on command line\n\n", cmd);
      return LVM_EINVALID_CMD_LINE;
   }

   LVM_CHECK_IOP;
   lvm_dont_interrupt ( 0);

   if ( ( lvm = open ( LVM_DEV, O_RDONLY)) == -1) {
      fprintf ( stderr, "%s -- ERROR opening device special \"%s\"\n\n",
                        cmd, LVM_DEV);
      return LVM_ELVMCHANGE_OPEN;
   }

   if ( opt_f == 0) {
      c = 0;
      while ( c != 'y' && c != 'n') {
         if ( c == '\n' || c == 0)
            printf ( "%s -- do you want to reset LVM [y/n]? ", cmd);
         c = tolower ( getchar ());
      }
   } else c = 'y';
   c1 = c;
   while ( c != '\n') c = tolower ( getchar ());
   if ( c1 == 'n') {
      printf ( "%s -- NOT resetting LVM\n\n", cmd);
      ret = 0;
   } else {
      if ( opt_v > 0) printf ( "%s -- resetting LVM ...\n", cmd);
      if ( ( ret = ioctl ( lvm, LVM_RESET, &cmd)) < 0) {
         fprintf ( stderr, "%s -- ERROR \"%s\" doing reset ioctl\n",
                           cmd, lvm_error ( ret));
         ret = LVM_ELVMCHANGE_RESET;
      } else {
         printf ( "%s -- LVM has been reset\n", cmd);
      }
   }

   lvm_interrupt ();
   close ( lvm);

   printf ( "\n");
   return ret;
}
