4 * Across-the-wire migration utility for Citadel
6 * Copyright (c) 2009 citadel.org
8 * This program is licensed to you under the terms of the GNU General Public License v3
18 #include <sys/types.h>
20 #include <sys/utsname.h>
28 #include <libcitadel.h>
33 #include "citadel_dirs.h"
41 int main(int argc, char *argv[])
45 char relhome[PATH_MAX]="";
46 char ctdldir[PATH_MAX]=CTDLDIR;
48 char sendcommand[PATH_MAX];
52 char socket_path[PATH_MAX];
53 char remote_user[256];
54 char remote_host[256];
55 char remote_sendcommand[PATH_MAX];
59 char spinning[4] = "-\\|/" ;
61 calc_dirs_n_files(relh, home, relhome, ctdldir, 0);
62 CtdlMakeTempFileName(socket_path, sizeof socket_path);
65 printf( "-------------------------------------------\n"
66 "Over-the-wire migration utility for Citadel\n"
67 "-------------------------------------------\n"
69 "This utility is designed to migrate your Citadel installation\n"
70 "to a new host system via a network connection, without disturbing\n"
71 "the source system. The target may be a different CPU architecture\n"
72 "and/or operating system. The source system should be running\n"
73 "Citadel %d.%02d or newer, and the target system should be running\n"
74 "either the same version or a newer version. You will also need\n"
75 "the 'rsync' utility, and OpenSSH v4 or newer.\n"
77 "You must run this utility on the TARGET SYSTEM. Any existing data\n"
78 "on this system will be ERASED.\n"
80 "Do you wish to continue? "
86 if ((fgets(yesno, sizeof yesno, stdin) == NULL) || (tolower(yesno[0]) != 'y')) {
90 printf("\n\nGreat! First we will check some things out here on our target\n"
91 "system to make sure it is ready to receive data.\n\n");
93 printf("Locating 'sendcommand' and checking connectivity to Citadel...\n");
94 snprintf(sendcommand, sizeof sendcommand, "%s/sendcommand", ctdl_utilbin_dir);
95 snprintf(cmd, sizeof cmd, "%s 'NOOP'", sendcommand);
96 exitcode = system(cmd);
98 printf("\nctdlmigrate was unable to attach to the Citadel server\n"
99 "here on the target system. Is Citadel running?\n\n");
102 printf("\nOK, this side is ready to go. Now we must connect to the source system.\n\n");
104 printf("Enter the host name or IP address of the source system\n"
105 "(example: ctdl.foo.org)\n"
108 printf("\nEnter the name of a user on %s who has full access to Citadel files\n"
109 "(usually root)\n--> ",
113 printf("\nEstablishing an SSH connection to the source system...\n\n");
115 snprintf(cmd, sizeof cmd, "ssh -MNf -S %s %s@%s", socket_path, remote_user, remote_host);
116 exitcode = system(cmd);
118 printf("\nctdlmigrate was unable to establish an SSH connection to the\n"
119 "source system, and cannot continue.\n\n");
123 printf("\nTesting a command over the connection...\n\n");
124 snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s 'echo Remote commands are executing successfully.'",
125 socket_path, remote_user, remote_host);
126 exitcode = system(cmd);
129 printf("Remote commands are not succeeding.\n\n");
133 printf("\nLocating the remote 'sendcommand' and Citadel installation...\n");
134 snprintf(remote_sendcommand, sizeof remote_sendcommand, "/usr/local/citadel/sendcommand");
135 snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
136 socket_path, remote_user, remote_host, remote_sendcommand);
137 exitcode = system(cmd);
139 snprintf(remote_sendcommand, sizeof remote_sendcommand, "/usr/sbin/sendcommand");
140 snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
141 socket_path, remote_user, remote_host, remote_sendcommand);
142 exitcode = system(cmd);
145 printf("\nUnable to locate Citadel programs on the remote system. Please enter\n"
146 "the name of the directory on %s which contains the 'sendcommand' program.\n"
147 "(example: /opt/foo/citadel)\n"
148 "--> ", remote_host);
150 snprintf(remote_sendcommand, sizeof remote_sendcommand, "%s/sendcommand", buf);
151 snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s NOOP",
152 socket_path, remote_user, remote_host, remote_sendcommand);
153 exitcode = system(cmd);
157 printf("ctdlmigrate was unable to attach to the remote Citadel system.\n\n");
161 printf("ctdlmigrate will now begin a database migration...\n");
163 snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s MIGR export",
164 socket_path, remote_user, remote_host, remote_sendcommand);
165 source_artv = popen(cmd, "r");
167 printf("\n%s\n\n", strerror(errno));
171 snprintf(cmd, sizeof cmd, "%s MIGR import", sendcommand);
172 target_artv = popen(cmd, "w");
174 printf("\n%s\n\n", strerror(errno));
178 while (fgets(buf, sizeof buf, source_artv) != NULL) {
179 fwrite(buf, strlen(buf), 1, target_artv);
181 if ((linecount % 100) == 0) {
182 printf("%c\r", spinning[((linecount / 100) % 4)]);
190 // FIXME handle -h on both sides
191 // FIXME kill the master ssh session
192 printf("If this program was finished we would do more. FIXME\n");