Back to index

citadel  8.12
Functions
ctdlmigrate.c File Reference
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <time.h>
#include <libcitadel.h>
#include "citadel.h"
#include "axdefs.h"
#include "sysdep.h"
#include "config.h"
#include "citadel_dirs.h"

Go to the source code of this file.

Functions

void getz (char *buf)
int main (int argc, char *argv[])

Function Documentation

void getz ( char *  buf)

Definition at line 55 of file ctdlmigrate.c.

                     {
       char *ptr;

       ptr = fgets(buf, 32767, stdin);
       if (!ptr) {
              buf[0] = 0;
              return;
       }

       ptr = strchr(buf, '\n');
       if (ptr) *ptr = 0;
}

Here is the caller graph for this function:

int main ( int  argc,
char *  argv[] 
)

Definition at line 72 of file ctdlmigrate.c.

{
       int relh=0;
       int home=0;
       char relhome[PATH_MAX]="";
       char ctdldir[PATH_MAX]=CTDLDIR;
       char yesno[5];
       char sendcommand[PATH_MAX];
       int cmdexit;
       char cmd[PATH_MAX];
       char buf[PATH_MAX];
       char socket_path[PATH_MAX];
       char remote_user[256];
       char remote_host[256];
       char remote_sendcommand[PATH_MAX];
       FILE *sourcefp = NULL;
       FILE *targetfp = NULL;
       int linecount = 0;
       char spinning[4] = "-\\|/" ;
       int exitcode = 0;
       
       calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
       CtdlMakeTempFileName(socket_path, sizeof socket_path);

       cmdexit = system("clear");
       printf(       "-------------------------------------------\n"
              "Over-the-wire migration utility for Citadel\n"
              "-------------------------------------------\n"
              "\n"
              "This utility is designed to migrate your Citadel installation\n"
              "to a new host system via a network connection, without disturbing\n"
              "the source system.  The target may be a different CPU architecture\n"
              "and/or operating system.  The source system should be running\n"
              "Citadel %d.%02d or newer, and the target system should be running\n"
              "either the same version or a newer version.  You will also need\n"
              "the 'rsync' utility, and OpenSSH v4 or newer.\n"
              "\n"
              "You must run this utility on the TARGET SYSTEM.  Any existing data\n"
              "on this system will be ERASED.\n"
              "\n"
              "Do you wish to continue? "
              ,
              EXPORT_REV_MIN / 100,
              EXPORT_REV_MIN % 100
       );

       if ((fgets(yesno, sizeof yesno, stdin) == NULL) || (tolower(yesno[0]) != 'y')) {
              exit(0);
       }

       printf("\n\nGreat!  First we will check some things out here on our target\n"
              "system to make sure it is ready to receive data.\n\n");

       printf("Locating 'sendcommand' and checking connectivity to Citadel...\n");
       snprintf(sendcommand, sizeof sendcommand, "%s/sendcommand", ctdl_utilbin_dir);
       snprintf(cmd, sizeof cmd, "%s 'NOOP'", sendcommand);
       cmdexit = system(cmd);
       if (cmdexit != 0) {
              printf("\nctdlmigrate was unable to attach to the Citadel server\n"
                     "here on the target system.  Is Citadel running?\n\n");
              exit(1);
       }
       printf("\nOK, this side is ready to go.  Now we must connect to the source system.\n\n");

       printf("Enter the host name or IP address of the source system\n"
              "(example: ctdl.foo.org)\n"
              "--> ");
       getz(remote_host);
       printf("\nEnter the name of a user on %s who has full access to Citadel files\n"
              "(usually root)\n--> ",
              remote_host);
       getz(remote_user);

       printf("\nEstablishing an SSH connection to the source system...\n\n");
       unlink(socket_path);
       snprintf(cmd, sizeof cmd, "ssh -MNf -S %s %s@%s", socket_path, remote_user, remote_host);
       cmdexit = system(cmd);
       printf("\n");
       if (cmdexit != 0) {
              printf("This program was unable to establish an SSH session to the source system.\n\n");
              exitcode = cmdexit;
              goto THEEND;
       }

       printf("\nTesting a command over the connection...\n\n");
       snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s 'echo Remote commands are executing successfully.'",
              socket_path, remote_user, remote_host);
       cmdexit = system(cmd);
       printf("\n");
       if (cmdexit != 0) {
              printf("Remote commands are not succeeding.\n\n");
              exitcode = cmdexit;
              goto THEEND;
       }

       printf("\nLocating the remote 'sendcommand' and Citadel installation...\n");
       snprintf(remote_sendcommand, sizeof remote_sendcommand, "/usr/local/citadel/sendcommand");
       snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
              socket_path, remote_user, remote_host, remote_sendcommand);
       cmdexit = system(cmd);
       if (cmdexit != 0) {
              snprintf(remote_sendcommand, sizeof remote_sendcommand, "/usr/sbin/sendcommand");
              snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
                     socket_path, remote_user, remote_host, remote_sendcommand);
              cmdexit = system(cmd);
       }
       if (cmdexit != 0) {
              printf("\nUnable to locate Citadel programs on the remote system.  Please enter\n"
                     "the name of the directory on %s which contains the 'sendcommand' program.\n"
                     "(example: /opt/foo/citadel)\n"
                     "--> ", remote_host);
              getz(buf);
              snprintf(remote_sendcommand, sizeof remote_sendcommand, "%s/sendcommand", buf);
              snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
                     socket_path, remote_user, remote_host, remote_sendcommand);
              cmdexit = system(cmd);
       }
       printf("\n");
       if (cmdexit != 0) {
              printf("ctdlmigrate was unable to attach to the remote Citadel system.\n\n");
              exitcode = cmdexit;
              goto THEEND;
       }

       printf("ctdlmigrate will now begin a database migration...\n");

       snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s -w3600 MIGR export",
              socket_path, remote_user, remote_host, remote_sendcommand);
       sourcefp = popen(cmd, "r");
       if (!sourcefp) {
              printf("\n%s\n\n", strerror(errno));
              exitcode = 2;
              goto THEEND;
       }

       snprintf(cmd, sizeof cmd, "%s -w3600 MIGR import", sendcommand);
       targetfp = popen(cmd, "w");
       if (!targetfp) {
              printf("\n%s\n\n", strerror(errno));
              exitcode = 3;
              goto THEEND;
       }

       while (fgets(buf, sizeof buf, sourcefp) != NULL) {
              if (fwrite(buf, strlen(buf), 1, targetfp) < 1) {
                     exitcode = 4;
                     printf("%s\n", strerror(errno));
                     goto FAIL;
              }
              ++linecount;
              if ((linecount % 100) == 0) {
                     printf("%c\r", spinning[((linecount / 100) % 4)]);
                     fflush(stdout);
              }
       }

FAIL:  if (sourcefp) pclose(sourcefp);
       if (targetfp) pclose(targetfp);
       if (exitcode != 0) goto THEEND;

       /* We need to copy a bunch of other stuff, and will do so using rsync */

       snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s MIGR listdirs",
              socket_path, remote_user, remote_host, remote_sendcommand);
       sourcefp = popen(cmd, "r");
       if (!sourcefp) {
              printf("\n%s\n\n", strerror(errno));
              exitcode = 2;
              goto THEEND;
       }
       while ((fgets(buf, sizeof buf, sourcefp)) && (strcmp(buf, "000"))) {
              buf[strlen(buf)-1] = 0;

              if (!strncasecmp(buf, "bio|", 4)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[4], ctdl_bio_dir);
              }
              else if (!strncasecmp(buf, "files|", 6)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[6], ctdl_file_dir);
              }
              else if (!strncasecmp(buf, "userpics|", 9)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[9], ctdl_usrpic_dir);
              }
              else if (!strncasecmp(buf, "messages|", 9)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[9], ctdl_message_dir);
              }
              else if (!strncasecmp(buf, "netconfigs|", 11)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[11], ctdl_netcfg_dir);
              }
              else if (!strncasecmp(buf, "keys|", 5)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[5], ctdl_key_dir);
              }
              else if (!strncasecmp(buf, "images|", 7)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[7], ctdl_image_dir);
              }
              else if (!strncasecmp(buf, "info|", 5)) {
                     snprintf(cmd, sizeof cmd, "rsync -va --rsh='ssh -S %s' %s@%s:%s/ %s/",
                            socket_path, remote_user, remote_host, &buf[5], ctdl_info_dir);
              }
              else {
                     strcpy(cmd, "false");       /* cheap and sleazy way to throw an error */
              }
              printf("%s\n", cmd);
              cmdexit = system(cmd);
              if (cmdexit != 0) {
                     exitcode += cmdexit;
              }
       }
       pclose(sourcefp);

THEEND:       if (exitcode == 0) {
              printf("\n\n *** Citadel migration was successful! *** \n\n");
       }
       else {
              printf("\n\n *** Citadel migration was unsuccessful. *** \n\n");
       }
       printf("\nShutting down the socket connection...\n\n");
       snprintf(cmd, sizeof cmd, "ssh -S %s -N -O exit %s@%s",
              socket_path, remote_user, remote_host);
       cmdexit = system(cmd);
       printf("\n");
       if (cmdexit != 0) {
              printf("There was an error shutting down the socket.\n\n");
              exitcode = cmdexit;
       }

       unlink(socket_path);
       exit(exitcode);
}

Here is the call graph for this function: