/*
 * tools/vgexport.c
 *
 * Copyright (C) 1997 - 2002  Heinz Mauelshagen, Sistina Software
 *
 * May 1997
 * May,June,September 1998
 * October 1999
 * February 2000
 * February 2002
 *
 * 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
 *
 *    02/05/1998 - don't make LV name change in LV structs to avoid
 *                 usage of lv_create_name() because of free logical volume
 *                 name support
 *    03/05/1998 - enhanced error checking with lvm_tab_vg_remove()
 *    16/05/1998 - added lvmtab checking
 *    10/06/1998 - added -a option
 *    27/06/1998 - changed lvm_tab_* calling convention
 *    05/09/1998 - corrected some messages
 *               - used lvm_tab_vg_check_exist() instead of vg_check_exist()
 *               - checked for volume group activity first for
 *                 better performance
 *    06/10/1999 - implemented support for long options
 *    15/02/2000 - use lvm_error()
 *    23/01/2001 - added call to lvm_init (JT)
 *    09/04/2001 - Tidy usage message and command-line options.
 *    07/02/2002 - avoid using lvm_tab_* functions so that we still can
 *                 export in case we don't have cache files
 *
 */

#include <lvm_user.h>

char *cmd = NULL;

#ifdef DEBUG
int opt_d = 0;
#endif

void usage ( int ret)
{
   FILE *stream = stderr;

   if ( ret == 0) {
      stream = stdout;
      printf ( "%s (IOP %d)\n\n", lvm_version, LVM_LIB_IOP_VERSION);
      printf ( "%s -- unregister volume group from system\n", cmd);
   }

   fprintf ( stream, "\n%s "
             "[-a|--all] "
             DEBUG_HELP_2
             "[-h|--help]\n\t"
             "[-v|--verbose] "
             "[--version] "
             "VolumeGroupName [VolumeGroupName...]\n",
             cmd);
   exit ( ret);
}

int main ( int argc, char **argv) {
   int c = 0;
   int opt_a = 0;
   int opt_v = 0;
   int p = 0;
   int ret = 0;
   char *vg_name = NULL;
   char *options = "ah?v" DEBUG_SHORT_OPTION;
   struct option long_options[] = {
      { "all",     no_argument, NULL, 'a'},
      DEBUG_LONG_OPTION
      { "help",    no_argument, NULL, 'h'},
      { "verbose", no_argument, NULL, 'v'},
      { "version", no_argument, NULL, 22 },
      { NULL,      0,           NULL, 0},
   };
   char vg_name_exp[NAME_LEN] = { 0, };
   vg_t *vg = NULL;

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

   LVMTAB_CHECK;

   while ( ( c = getopt_long ( argc, argv, options,
                               long_options, NULL)) != EOF) {
      switch ( c) {

         case 'a':
            opt_a++;
            break;

         DEBUG_HANDLE_CASE_D;

         case 'h':
            usage ( 0);

         case 'v':
            opt_v++;
            break;

         case 22:
            printf ("%s: %s (IOP %d)\n", cmd, lvm_version, LVM_LIB_IOP_VERSION);
            return 0;

         default:
            fprintf ( stderr, "%s -- invalid command line option \"%c\"\n\n",
                      cmd, c);
         case '?':
            usage ( LVM_EINVALID_CMD_LINE);
      }
   }

   /* not until all commands are converted
   CMD_MINUS_CHK;
   */
   if ( optind < argc && *argv[optind] == '-') {
      fprintf ( stderr, "%s -- invalid option %s\n", cmd, argv[optind]);
      usage ( LVM_EINVALID_CMD_LINE);
   }
   LVM_CHECK_IOP;
   LVM_LOCK ( 0);

   if ( opt_a > 0) {
      argv = vg_check_exist_all_vg ();
      argc = optind = 0;
      if ( argv != NULL) while ( argv[argc] != NULL) argc++;
   
      if ( optind == argc) {
         printf ( "%s -- no volume groups found\n\n", cmd);
         usage ( LVM_EVGEXPORT_NO_VG);
      }
   } else if ( optind == argc) {
      fprintf ( stderr, "%s -- please give a volume group name\n\n", cmd);
      usage ( LVM_EVGEXPORT_VG_MISSING);
   }


   for ( ; optind < argc; optind++) {
      vg_name = argv[optind];

      if ( opt_v > 0) printf ( "%s -- checking volume group name\n", cmd);
      if ( vg_check_name ( vg_name) < 0) {
         fprintf ( stderr, "%s -- invalid volume group name \"%s\"\n",
                   cmd, vg_name);
         continue;
      }
   
      if ( opt_v > 0) printf ( "%s -- checking volume group activity\n", cmd);
      if ( vg_check_active ( vg_name) == TRUE) {
         fprintf ( stderr, "%s -- can't export active volume group \"%s\"\n",
                   cmd, vg_name);
         continue;
      }

      memset ( vg_name_exp, 0, sizeof ( vg_name_exp));
      snprintf ( vg_name_exp, sizeof ( vg_name_exp) - 1,
                              "%s%s", vg_name, EXPORTED);
      if ( ( ret = vg_check_exist ( vg_name_exp)) != TRUE) {
         if ( ret == -LVM_EVG_READ_VG_EXPORTED) {
            fprintf ( stderr, "%s -- a volume group named \"%s\" is "
                              "already exported\n",
                              cmd, vg_name);
            continue;
         }
      }

      if ( opt_v > 0) printf ( "%s -- reading data of volume group \"%s\" "
                               "from disk(s)\n", cmd, vg_name);
      if ( ( ret = vg_read_with_pv_and_lv ( vg_name, &vg)) != 0) {
         fprintf ( stderr, "%s -- ERROR \"%s\" reading data of volume "
                           "group \"%s\"\n\n",
                           cmd, lvm_error ( ret), vg_name);
         continue;
      }

      if ( opt_v > 0) printf ( "%s -- checking for physical volumes in "
                               "volume group \"%s\"\n", cmd, vg_name);
      if ( vg->pv_cur == 0) {
         fprintf ( stderr, "%s -- no physical volumes in volume group \"%s\"\n",
                   cmd, vg_name);
         continue;
      }
   
      if ( opt_v > 0) printf ( "%s -- checking volume group \"%s\" "
                               "consistency\n", cmd, vg_name);
      if ( ( ret = vg_check_consistency_with_pv_and_lv ( vg)) != 0) {
         fprintf ( stderr, "%s -- ERROR \"%s\" volume group \"%s\" is "
                           "inconsistent\n\n",
                           cmd, lvm_error ( ret), vg_name);
         continue;
      }

      /* set my export marker */
      if ( opt_v > 0) printf ( "%s -- setting up volume group \"%s\" "
                               "for export\n",
                               cmd, vg_name);
      system_id_set_exported ( vg->pv[0]->system_id);
      strcat ( vg->pv[0]->vg_name, EXPORTED);

      /* correct it in the rest of the PVs */
      for ( p = 1; vg->pv[p] != NULL; p++) {
         strcpy ( vg->pv[p]->system_id, vg->pv[0]->system_id);
         strcpy ( vg->pv[p]->vg_name, vg->pv[0]->vg_name);
      }

      vg->vg_status |= VG_EXPORTED;
      strcpy ( vg->vg_name, vg->pv[0]->vg_name);

      if ( opt_v > 0) printf ( "%s -- exporting volume group \"%s\" with "
                               "%u physical and %u logical volumes\n",
                               cmd, vg_name, vg->pv_cur, vg->lv_cur);
   
      lvm_dont_interrupt ( 0);

      if ( ( ret = vg_write_with_pv_and_lv ( vg)) < 0) {
         fprintf ( stderr, "%s -- ERROR \"%s\" storing volume group "
                           "data on disk(s)\n",
                           cmd, lvm_error ( ret));
      }

      if ( opt_v > 0) printf ( "%s -- removing special files of volume "
                               "group \"%s\"\n",
                               cmd, vg_name);
      vg_remove_dir_and_group_and_nodes ( vg_name);
   
      if ( ( ret = lvm_tab_vg_remove ( vg_name)) < 0) {
         fprintf ( stderr, "%s -- ERROR \"%s\" removing volume group \"%s\" "
                           "from \"%s\"\n",
                           cmd, lvm_error ( ret), vg_name, LVMTAB);
      }

      lvm_interrupt ();

      printf ( "%s -- volume group \"%s\"%s sucessfully exported\n",
               cmd, vg_name, ret < 0 ? " NOT" : "");

   }

   LVM_UNLOCK ( 0);

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