aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plpbackup/plpbackup.cc1401
1 files changed, 132 insertions, 1269 deletions
diff --git a/plpbackup/plpbackup.cc b/plpbackup/plpbackup.cc
index c843638..7fc3047 100644
--- a/plpbackup/plpbackup.cc
+++ b/plpbackup/plpbackup.cc
@@ -25,159 +25,39 @@
#include <config.h>
#endif
-#include <fstream>
-#include <iostream>
-#include <iomanip>
-#include <vector>
-#include <set>
-
#include <plpintl.h>
#include <ppsocket.h>
#include <rfsv.h>
#include <rfsvfactory.h>
#include <rpcs.h>
#include <rpcsfactory.h>
-#include <bufferstore.h>
-#include <bufferarray.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <dirent.h>
-#include <ctype.h>
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <signal.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <pwd.h>
+#include <time.h>
#include <getopt.h>
-#include <fcntl.h>
using namespace std;
-bool full = false;
-bool S5mx = false;
-bool doRestore = false;
-bool doBackup = false;
-bool skipError = false;
+bool doStart = false;
+bool doStop = false;
bool doAbort = false;
-bool overWriteAll = false;
-
-int verbose = 0;
-int caughtSig = 0;
-unsigned long backupSize = 0;
-unsigned long backupCount = 0;
-unsigned long totalBytes = 0;
-unsigned long fileSize = 0;
+int verbose = 0;
+int caughtSig = 0;
-PlpDir toBackup;
-PlpDir toRestore;
-vector<string> driveList;
-vector<string> archList;
-vector<string> savedCommands;
-set<string> overWriteList;
rfsv *Rfsv;
rpcs *Rpcs;
static RETSIGTYPE
sig_handler(int sig)
{
- caughtSig = sig;
- signal(sig, sig_handler);
-};
-
-static const char * const
-getHomeDir()
-{
- struct passwd *pw = getpwuid(getuid());
- if (pw && pw->pw_dir && strlen(pw->pw_dir))
- return pw->pw_dir;
- else
- cerr << _("Could not get user's home directory from /etc/passwd")
- << endl;
- return "";
-}
-
-static const char * const
-generateBackupName()
-{
- time_t now = time(0);
- Enum<rfsv::errs> res;
- u_int64_t machineUID;
- char tstr[80];
- static char nbuf[4096];
-
- Enum<rpcs::machs> machType;
-
- Rpcs->getMachineType(machType);
- if (machType == rpcs::PSI_MACH_S5) {
- rpcs::machineInfo mi;
- if ((res = Rpcs->getMachineInfo(mi)) != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not get machine UID") << endl;
- exit(1);
- }
- machineUID = mi.machineUID;
- } else {
- // On a SIBO, first check for a file 'SYS$PT.CFG' on the default
- // directory. If it exists, read the UID from it. Otherwise
- // calculate a virtual machine UID from the OwnerInfo data and
- // write it to that file.
- bufferArray b;
- u_int32_t handle;
- u_int32_t count;
-
- res = Rfsv->fopen(Rfsv->opMode(rfsv::PSI_O_RDONLY),
- "SYS$PT.CFG", handle);
- if (res == rfsv::E_PSI_GEN_NONE) {
- res = Rfsv->fread(handle, (unsigned char *)&machineUID,
- sizeof(machineUID), count);
- Rfsv->fclose(handle);
- if ((res != rfsv::E_PSI_GEN_NONE) || (count != sizeof(machineUID))) {
- cerr << _("Could not read SIBO UID file") << endl;
- exit(1);
- }
- } else {
- if ((res = Rpcs->getOwnerInfo(b)) != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not get Psion owner info") << endl;
- exit(1);
- }
- machineUID = 0;
- string oi = "";
- while (!b.empty()) {
- oi += b.pop().getString();
- oi += "\n";
- }
- const char *p = oi.c_str();
- unsigned long long z;
- int i = 0;
-
- while (*p) {
- z = *p;
- machineUID ^= (z << i);
- p++; i++;
- i &= ((sizeof(machineUID) * 8) - 1);
- }
- res = Rfsv->fcreatefile(Rfsv->opMode(rfsv::PSI_O_RDWR),
- "SYS$PT.CFG", handle);
- if (res == rfsv::E_PSI_GEN_NONE) {
- res = Rfsv->fwrite(handle, (const unsigned char *)&machineUID,
- sizeof(machineUID), count);
- Rfsv->fclose(handle);
- }
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not write SIBO UID file ") << res << endl;
- exit(1);
- }
- }
- }
- strftime(tstr, sizeof(tstr), "-%Y-%m-%d-%H-%M-%S", localtime(&now));
- sprintf(nbuf, "%s/plpbackup/%016llx/%c%s", getHomeDir(),
- machineUID, full ? 'F' : 'I', tstr);
- return nbuf;
+ caughtSig = sig;
+ signal(sig, sig_handler);
}
static bool
@@ -185,20 +65,20 @@ checkAbort()
{
if (caughtSig) {
if (verbose > 0)
- cout << endl;
- cout << _("Got signal ");
+ cerr << endl;
+ cerr << _("Got signal ");
switch (caughtSig) {
- case SIGTERM:
- cout << "SIGTERM";
- break;
- case SIGINT:
- cout << "SIGINT";
- break;
- default:
- cout << caughtSig;
+ case SIGTERM:
+ cerr << "SIGTERM";
+ break;
+ case SIGINT:
+ cerr << "SIGINT";
+ break;
+ default:
+ cerr << caughtSig;
}
- cout << endl;
- cout << _("Abort? (y/N) ") << flush;
+ cerr << endl;
+ cerr << _("Abort? (y/N) ") << flush;
const char *validA = _("Y");
char answer;
cin >> answer;
@@ -210,18 +90,24 @@ checkAbort()
}
static int
-stopPrograms() {
+stopPrograms(const char *file) {
Enum<rfsv::errs> res;
processList tmp;
+ FILE *fp = fopen(file, "w");
+ if (fp == NULL) {
+ cerr << _("Could not open command list file ") << file << endl;
+ return 1;
+ }
if (verbose > 0)
- cout << _("Stopping programs ...") << endl;
+ cerr << _("Stopping programs, writing list to ...") << file << endl;
if ((res = Rpcs->queryPrograms(tmp)) != rfsv::E_PSI_GEN_NONE) {
cerr << _("plpbackup: Could not get process list: ") << res << endl;
return 1;
} else {
for (processList::iterator i = tmp.begin(); i != tmp.end(); i++) {
- savedCommands.push_back(i->getArgs());
+ fputs(i->getArgs(), fp);
+ fputc('\n', fp);
Rpcs->stopProgram(i->getProcId());
}
time_t tstart = time(0) + 5;
@@ -236,31 +122,65 @@ stopPrograms() {
if (tmp.empty())
break;
if (time(0) > tstart) {
- cout << _(
- "Could not stop all processes. Please stop running\n"
- "programs manually on the Psion, then hit return.") << flush;
+ cerr << _(
+ "Could not stop all processes. Please stop running\n"
+ "programs manually on the Psion, then hit return.") << flush;
cin.getline((char *)&tstart, 1);
tstart = time(0) + 5;
}
}
}
+ fclose(fp);
return 0;
}
+static char *
+getln(FILE *fp)
+{
+ size_t len = 256;
+ int c;
+ char *l = (char *)malloc(len), *s = l;
+
+ assert(l);
+ for (c = getc(fp); c != '\n' && c != EOF; c = getc(fp)) {
+ if (s == l + len) {
+ l = (char *)realloc(l, len * 2);
+ assert(l);
+ len *= 2;
+ }
+ *s++ = c;
+ }
+ if (s == l + len) {
+ l = (char *)realloc(l, len + 1);
+ assert(l);
+ }
+ *s++ = '\0';
+
+ l = (char *)realloc(l, s - l);
+ assert(l);
+ return l;
+}
+
static int
-startPrograms() {
+startPrograms(const char *file) {
Enum<rfsv::errs> res;
+ FILE *fp = fopen(file, "r");
+ string cmd;
+ if (fp == NULL) {
+ cerr << _("Could not open command list file ") << file << endl;
+ return 1;
+ }
if (verbose > 0)
- cout << _("Restarting programs ...") << endl;
- for (unsigned int i = 0; i < savedCommands.size(); i++) {
- int firstBlank = savedCommands[i].find(' ');
- string cmd = string(savedCommands[i], 0, firstBlank);
- string arg = string(savedCommands[i], firstBlank + 1);
+ cerr << _("Restarting programs, reading list from ") << file << endl;
+ for (cmd = string(getln(fp)); cmd.length() > 0; cmd = string(getln(fp))) {
+ int firstBlank = cmd.find(' ');
+ string prog = string(cmd, 0, firstBlank);
+ string arg = string(cmd, firstBlank + 1);
- if (!cmd.empty()) {
+ if (!prog.empty()) {
if (verbose > 1)
- cout << cmd << " " << arg << endl;
+ cerr << cmd << endl;
// Workaround for broken programs like Backlite. These do not store
// the full program path. In that case we try running the arg1 which
@@ -269,14 +189,14 @@ startPrograms() {
(arg[0] <= 'Z'))
res = Rpcs->execProgram(arg.c_str(), "");
else
- res = Rpcs->execProgram(cmd.c_str(), arg.c_str());
+ res = Rpcs->execProgram(prog.c_str(), arg.c_str());
if (res != rfsv::E_PSI_GEN_NONE) {
// If we got an error here, that happened probably because
// we have no path at all (e.g. Macro5) and the program is
// not registered in the Psion's path properly. Now try
// the usual \System\Apps\<AppName>\<AppName>.app
// on all drives.
- if (cmd.find('\\') == cmd.npos) {
+ if (prog.find('\\') == prog.npos) {
u_int32_t devbits;
if ((res = Rfsv->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) {
int i;
@@ -284,7 +204,7 @@ startPrograms() {
if (devbits & (1 << i)) {
string tmp;
tmp = (char)('A' + i) + ":\\System\\Apps\\" +
- cmd + "\\" + cmd + ".app";
+ prog + "\\" + prog + ".app";
res = Rpcs->execProgram(tmp.c_str(), "");
if (res == rfsv::E_PSI_GEN_NONE)
break;
@@ -294,7 +214,7 @@ startPrograms() {
}
}
if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << "Could not start " << cmd << " " << arg << endl;
+ cerr << "Could not start " << cmd << endl;
cerr << "Error: " << res << endl;
}
}
@@ -302,1064 +222,32 @@ startPrograms() {
return 0;
}
-string
-unix2psion(const char * const path) {
- string tmp = path;
- int pos;
-
- while ((pos = tmp.find('/')) != -1)
- tmp.replace(pos, 1, "\\");
- while ((pos = tmp.find("%2f")) != -1)
- tmp.replace(pos, 3, "/");
- while ((pos = tmp.find("%25")) != -1)
- tmp.replace(pos, 3, "%");
- return tmp;
-}
-
-string
-psion2unix(const char * const path) {
- string tmp;
-
- for (const char *p = path; p && *p; p++)
- switch (*p) {
- case '%':
- tmp += "%25";
- break;
- case '/':
- tmp += "%2f";
- break;
- case '\\':
- tmp += "/";
- break;
- default:
- tmp += *p;
- }
- return tmp;
-}
-
-static void
-collectFiles(bool &found, const char *dir) {
- Enum<rfsv::errs> res;
- PlpDir files;
- string tmp;
-
- tmp = dir;
- tmp += "\\";
- if ((res = Rfsv->dir(tmp.c_str(), files)) != rfsv::E_PSI_GEN_NONE)
- cerr << "Error: " << res << endl;
- else
- for (unsigned int i = 0; i < files.size(); i++) {
- PlpDirent e = files[i];
-
- if (checkAbort())
- return;
- // long size = s.getDWord(4);
- long attr = e.getAttr();
- tmp = dir;
- tmp += "\\";
- tmp += e.getName();
- if (attr & rfsv::PSI_A_DIR) {
- collectFiles(found, tmp.c_str());
- } else {
- if ((attr & rfsv::PSI_A_ARCHIVE) || full) {
- e.setName(tmp.c_str());
- toBackup.push_back(e);
- found |= true;
- }
- }
- }
-}
-
-static int
-reportProgress(void *, u_int32_t size)
-{
- unsigned long percent = 0;
- char pstr[10];
- char bstr[10];
-
- if (checkAbort())
- return 0;
- if (verbose < 1)
- return 1;
- switch (verbose) {
- case 1:
- if (backupSize == 0)
- percent = 100;
- else
- percent = (totalBytes + size) * 100 / backupSize;
- break;
- case 2:
- if (fileSize == 0)
- percent = 100;
- else
- percent = size * 100 / fileSize;
- break;
- }
- sprintf(pstr, " %3ld%%", percent);
- memset(bstr, 8, sizeof(bstr));
- bstr[strlen(pstr)] = '\0';
- printf("%s%s", pstr, bstr);
- fflush(stdout);
- return 1;
-}
-
-static cpCallback_t cab = reportProgress;
-
-static int
-mkdirp(const char *_path) {
- char *path = strdup(_path);
- char *p = strchr(path, '/');
-
- while (p) {
- char csave = *(++p);
- *p = '\0';
- switch (mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP)) {
- struct stat stbuf;
-
- case 0:
- break;
- default:
- if (errno != EEXIST) {
- perror(path);
- free(path);
- return 1;
- }
- stat(path, &stbuf);
- if (!S_ISDIR(stbuf.st_mode)) {
- perror(path);
- free(path);
- return 1;
- }
- break;
- }
- *p++ = csave;
- p = strchr(p, '/');
- }
- free(path);
- return 0;
-}
-
-static void
-rmrf(const char *_path)
-{
- DIR *d = opendir(_path);
- if (d) {
- struct dirent *de;
- while ((de = readdir(d))) {
- struct stat st;
- if ((de->d_name[0] == '.') &&
- ((de->d_name[1] == '\0') ||
- ((de->d_name[1] == '.') &&
- (de->d_name[2] == '\0'))))
- continue;
- string path = _path;
- path += "/";
- path += de->d_name;
- if (stat(path.c_str(), &st) == 0) {
- if (S_ISDIR(st.st_mode))
- rmrf(path.c_str());
- else
- unlink(path.c_str());
- }
- }
- }
- closedir(d);
- rmdir(_path);
-}
-
-static void
-startMessage(const char *arch)
-{
- if (verbose >= 0) {
- cout << _("Performing ");
- if (doRestore)
- cout << _("restore");
- else
- cout << (full ? _("full") : _("incremental")) << _(" backup");
- cout << _(" of ");
- if (driveList.empty())
- cout << _("all drives");
- else {
- cout << _("Drive ");
- for (unsigned int i = 0; i < driveList.size(); i++) {
- cout << driveList[i++];
- if (i < (driveList.size() - 1))
- cout << ", ";
- else {
- if (driveList.size() > 1)
- cout << _(" and ");
- }
- }
- }
- if (arch) {
- if (doBackup)
- cout << _(" to ") << arch;
- if (doRestore)
- cout << _(" from ") << arch;
- }
- cout << endl;
- }
-
-}
-
-static double
-tdiff(struct timeval *start, struct timeval *end)
-{
- double s = (double)start->tv_sec * 1000000.0;
- double e = (double)end->tv_sec * 1000000.0;
- s += start->tv_usec;
- e += end->tv_usec;
- return (e - s) / 1000000.0;
-}
-
-static int
-editfile(char *name)
-{
- int shin, shout, sherr;
- int mode_out, mode_err;
- int status;
- int rc = -1;
- int rerrno = 0;
- int pid, w;
-
-#ifdef POSIX_SIGNALS
- sigset_t sigset_mask, sigset_omask;
- struct sigaction act, iact, qact;
-
-#else
-#ifdef BSD_SIGNALS
- int mask;
- struct sigvec vec, ivec, qvec;
-
-#else
- RETSIGTYPE (*istat) (int), (*qstat) (int);
-#endif
-#endif
-
- /* setup default file descriptor numbers */
- shin = 0;
- shout = 1;
- sherr = 2;
-
- /* set the file modes for stdout and stderr */
- mode_out = mode_err = O_WRONLY | O_CREAT;
-
- /* Make sure we don't flush this twice, once in the subprocess. */
- fflush (stdout);
- fflush (stderr);
-
- /* The output files, if any, are now created. Do the fork and dups.
-
- We use vfork not so much for a performance boost (the
- performance boost, if any, is modest on most modern unices),
- but for the sake of systems without a memory management unit,
- which find it difficult or impossible to implement fork at all
- (e.g. Amiga). The other solution is spawn (see
- windows-NT/run.c). */
-
-#ifdef HAVE_VFORK
- pid = vfork ();
-#else
- pid = fork ();
-#endif
- if (pid == 0)
- {
-
-#ifdef SETXID_SUPPORT
- /*
- ** This prevents a user from creating a privileged shell
- ** from the text editor when the SETXID_SUPPORT option is selected.
- */
- if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
- {
- error (0, errno, "cannot set egid to gid");
- _exit (127);
- }
-#endif
-
- /* dup'ing is done. try to run it now */
- char *editor = getenv("EDITOR");
- if (!editor)
- editor = "vi";
- execlp (editor, editor, name, NULL);
- perror(editor);
- _exit (127);
- }
- else if (pid == -1)
- {
- rerrno = errno;
- goto out;
- }
-
- /* the parent. Ignore some signals for now */
-#ifdef POSIX_SIGNALS
- act.sa_handler = SIG_IGN;
- (void) sigemptyset (&act.sa_mask);
- act.sa_flags = 0;
- (void) sigaction (SIGINT, &act, &iact);
- (void) sigaction (SIGQUIT, &act, &qact);
-#else
-#ifdef BSD_SIGNALS
- memset ((char *) &vec, 0, sizeof (vec));
- vec.sv_handler = SIG_IGN;
- (void) sigvec (SIGINT, &vec, &ivec);
- (void) sigvec (SIGQUIT, &vec, &qvec);
-#else
- istat = signal (SIGINT, SIG_IGN);
- qstat = signal (SIGQUIT, SIG_IGN);
-#endif
-#endif
-
- /* wait for our process to die and munge return status */
-#ifdef POSIX_SIGNALS
- while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- ;
-#else
- while ((w = wait (&status)) != pid) {
- if (w == -1 && errno != EINTR)
- break;
- }
-#endif
-
- if (w == -1) {
- rc = -1;
- rerrno = errno;
- }
-#ifndef VMS /* status is return status */
- else if (WIFEXITED (status))
- rc = WEXITSTATUS (status);
- else if (WIFSIGNALED (status)) {
- if (WTERMSIG (status) == SIGPIPE)
- perror("broken pipe");
- rc = 2;
- } else
- rc = 1;
-#else /* VMS */
- rc = WEXITSTATUS (status);
-#endif /* VMS */
-
- /* restore the signals */
-#ifdef POSIX_SIGNALS
- (void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
- (void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
-#else
-#ifdef BSD_SIGNALS
- (void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
- (void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
-#else
- (void) signal (SIGINT, istat);
- (void) signal (SIGQUIT, qstat);
-#endif
-#endif
-
- out:
- if (rerrno)
- errno = rerrno;
- return (rc);
-}
-
-static void
-collectIndex(FILE *f, const char *archname)
-{
- char buf[1024];
- string drives;
- int i;
-
- PlpDir indexSel;
- PlpDir indexRestore;
- while (fgets(buf, sizeof(buf), f)) {
- unsigned long attr;
- unsigned long size;
- unsigned long timeLo;
- unsigned long timeHi;
- char drive = buf[36];
-
- char *p = strrchr(buf, '\n');
- if (p)
- *p = '\0';
- if (drive != '!') {
- sscanf(buf, "%08lx %08lx %08lx %08lx ",
- &timeHi, &timeLo, &size, &attr);
- PlpDirent e(size, attr, timeHi, timeLo, &buf[36]);
- indexSel.push_back(e);
- if (drives.find(drive) == drives.npos)
- drives += drive;
- }
- }
- // drives now contains the drive-chars of all drives found in
- // the backup.
- if (!drives.empty()) {
- cout << _("It contains Backups of drive ");
- for (i = 0; i < drives.size(); i++) {
- if (i>0) {
- if (i < (drives.size() - 1))
- cout << ", ";
- else
- if (drives.size() > 1)
- cout << _(" and ");
- }
- cout << drives[i] << ":";
- }
- cout << endl;
-
- // Check, if one of the drives is in driveList (commandline args)
- bool select = false;
- for (i = 0; i < driveList.size(); i++) {
- if (drives.find(driveList[i][0]) != drives.npos)
- select = true;
- }
- if (select) {
- cout << _("Select (I)ndividual files, (W)hole archive, (N)one "
- "from this archive? (I/W/N) ") << flush;
- string validA = _("IWA");
- char answer;
- cin >> answer;
- FILE *tf;
- int fd;
- switch (validA.find(toupper(answer))) {
- case 0:
- strcpy(buf, "/tmp/plpbackupL_XXXXXX");
- fd = mkstemp(buf);
- if (fd == -1) {
- perror("mkstemp");
- exit(-1);
- }
- tf = fdopen(fd, "w");
- fprintf(tf, "# Edit this file to you needs and save it\n");
- fprintf(tf, "# Change the 'N' in the first column to 'Y'\n");
- fprintf(tf, "# if you want a file to be restored.\n");
- fprintf(tf, "# DO NOT INSERT ANY LINES!\n");
- for (i = 0; i < indexSel.size(); i++)
- for (int j = 0; j < driveList.size(); j++)
- if (*(indexSel[i].getName()) == driveList[j][0])
- fprintf(tf, "N %s\n", indexSel[i].getName());
- fclose(tf);
- if (editfile(buf) == -1) {
- perror(_("Could not run external editor"));
- unlink(buf);
- exit(-1);
- }
- tf = fopen(buf, "r");
- if (!tf) {
- perror(buf);
- unlink(buf);
- exit(-1);
- }
- unlink(buf);
- while (fgets(buf, sizeof(buf), tf)) {
- char *p = strrchr(buf, '\n');
- if (p)
- *p = '\0';
- if (buf[0] == 'Y') {
- for (i = 0; i < indexSel.size(); i++)
- if (!strcmp(indexSel[i].getName(), &buf[2]))
- indexRestore.push_back(indexSel[i]);
- }
- }
- fclose(tf);
- break;
- case 1:
- for (i = 0; i < indexSel.size(); i++)
- for (int j = 0; j < driveList.size(); j++)
- if (*(indexSel[i].getName()) == driveList[j][0])
- indexRestore.push_back(indexSel[i]);
- break;
- case 2:
- return;
- }
- } else
- cout << _("Archive skipped, because it does not contain any "
- "files on selected drives") << endl;
- }
- if (!indexRestore.empty()) {
- PlpDirent e(0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, archname);
- toRestore.push_back(e);
- for (i = 0; i < indexRestore.size(); i++)
- toRestore.push_back(indexRestore[i]);
- }
-}
-
-static bool
-askOverwrite(PlpDirent e)
-{
- if (overWriteAll)
- return true;
- const char *fn = e.getName();
- if (overWriteList.find(string(fn)) != overWriteList.end())
- return true;
- PlpDirent old;
- Enum<rfsv::errs> res = Rfsv->fgeteattr(fn, old);
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << "Could not get attributes of " << fn << ": " << res << endl;
- return false;
- }
-
- // Don't ask if size and attribs are same
- if ((old.getSize() == e.getSize()) &&
- ((old.getAttr() & ~rfsv::PSI_A_ARCHIVE) ==
- (e.getAttr() & ~rfsv::PSI_A_ARCHIVE)))
- return true;
-
- cout << "The file " << fn << endl;
- cout << "already exists on the Psion with different attributes/size"
- << endl;
- cout << "On the psion:" << endl;
- cout << " Size: " << old.getSize() << endl;
- cout << " Date: " << old.getPsiTime() << endl;
- cout << " Attr: " << Rfsv->attr2String(old.getAttr()).c_str() << endl;
- cout << "In the backup:" << endl;
- cout << " Size: " << e.getSize() << endl;
- cout << " Date: " << e.getPsiTime() << endl;
- cout << " Attr: " << Rfsv->attr2String(e.getAttr()).c_str() << endl;
- while (1) {
- cout << _("(O)verwrite, overwrite (A)ll, (S)kip? (O/A/S) ") << flush;
- string validA = _("OAS");
- char answer;
- cin >> answer;
- switch (validA.find(toupper(answer))) {
- case 0:
- return true;
- case 1:
- overWriteAll = true;
- return true;
- case 2:
- return false;
- }
- }
- return false; // Default
-}
-
-static int
-cps(unsigned long size, struct timeval *start, struct timeval *end)
-{
- double t = tdiff(start, end);
- if (t == 0.0)
- return 99999;
- else
- return (int)(((double)size) / t);
-}
-
-static void
-runRestore()
-{
- unsigned int i;
- char indexbuf[40];
- string indexfile;
- struct timeval start_tv, end_tv, cstart_tv, cend_tv;
-
- for (i = 0; i < archList.size(); i++) {
- indexfile = archList[i] + "/KPsionFullIndex";
- char backupType = '?';
- FILE *f = fopen(indexfile.c_str(), "r");
- if (!f) {
- indexfile = archList[i] + "/KPsionIncrementalIndex";
- if (!f) {
- perror(_("Could not get backup index"));
- continue;
- }
- }
- fgets(indexbuf, sizeof(indexbuf), f);
- if (!strncmp(indexbuf, "#plpbackup index ", 17))
- backupType = indexbuf[17];
- switch (backupType) {
- case 'F':
- cout << "'" << archList[i] << _("' is a full backup") << endl;
- collectIndex(f, archList[i].c_str());
- break;
- case 'I':
- cout << "'" << archList[i] << _("' is an incremental backup")
- << endl;
- collectIndex(f, archList[i].c_str());
- break;
- default:
- cerr << "'" << archList[i] << _("' is NOT a plpbackup") << endl;
- break;
- }
- pclose(f);
- }
- if (!toRestore.empty()) {
- gettimeofday(&start_tv, NULL);
- backupSize = backupCount = 0;
- // Calculate number of files and total bytecount
- for (i = 0; i < toRestore.size(); i++) {
- if (toRestore[i].getSize() != 0xdeadbeef) {
- backupSize += toRestore[i].getSize();
- backupCount++;
- }
- }
- // Stop all programs on Psion
- stopPrograms();
- string dest;
- string pDir;
- for (i = 0; i < toRestore.size(); i++) {
- PlpDirent e = toRestore[i];
- Enum<rfsv::errs> res;
- u_int32_t handle;
- struct timeval fstart_tv, fend_tv;
- const char *fn = e.getName();
-
- if ((e.getSize() == 0xdeadbeef) && (e.getAttr() == 0xdeadbeef) &&
- (e.getPsiTime().getPsiTimeLo() == 0xdeadbeef) &&
- (e.getPsiTime().getPsiTimeHi() == 0xdeadbeef)) {
-
- continue;
- }
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Restore aborted by user") << endl;
- return;
- }
- dest = archList[i];
- dest += '/';
- dest += psion2unix(fn);
- fileSize = e.getSize();
- if (verbose > 1)
- cout << _("Restore ") << fn << flush;
-
- string cpDir(fn);
- int bslash = cpDir.rfind('\\');
- if (bslash != cpDir.npos)
- cpDir.resize(bslash);
-
- if (pDir != cpDir) {
- pDir = cpDir;
- if (pDir.size() > 2) {
- res = Rfsv->mkdir(pDir.c_str());
- if ((res != rfsv::E_PSI_GEN_NONE) &&
- (res != rfsv::E_PSI_FILE_EXIST)) {
- cerr << _("Could not create directory ") << pDir << ": "
- << res << endl;
- continue;
- }
- }
- }
-
- res = Rfsv->fcreatefile(
- Rfsv->opMode(rfsv::PSI_O_RDWR), fn, handle);
- if (res == rfsv::E_PSI_FILE_EXIST) {
- if (!askOverwrite(e))
- continue;
- res = Rfsv->freplacefile(
- Rfsv->opMode(rfsv::PSI_O_RDWR), fn, handle);
- }
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not create ") << fn << ": " << res << endl;
- continue;
- }
- Rfsv->fclose(handle);
- gettimeofday(&fstart_tv, NULL);
- res = Rfsv->copyToPsion(dest.c_str(), fn, NULL, cab);
- if (res == rfsv::E_PSI_GEN_NONE) {
- u_int32_t oldattr;
- res = Rfsv->fgetattr(fn, oldattr);
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not get attributes of ") << fn << ": "
- << res << endl;
- continue;
- }
- u_int32_t mask = e.getAttr() ^ oldattr;
- u_int32_t sattr = e.getAttr() & mask;
- u_int32_t dattr = ~sattr & mask;
- int retry = 10;
- // Retry, because file sometimes takes some time
- // to close;
- do {
- res = Rfsv->fsetattr(fn, sattr, dattr);
- if (res != rfsv::E_PSI_GEN_NONE)
- usleep(100000);
- retry--;
- } while ((res != rfsv::E_PSI_GEN_NONE) && (retry > 0));
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not set attributes of") << fn << ": "
- << res << endl;
- continue;
- }
- retry = 10;
- do {
- res = Rfsv->fsetmtime(fn, e.getPsiTime());
- if (res != rfsv::E_PSI_GEN_NONE)
- usleep(100000);
- retry--;
- } while ((res != rfsv::E_PSI_GEN_NONE) && (retry > 0));
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Could not set modification time of ") << fn
- << ": " << res << endl;
- continue;
- }
- overWriteList.insert(string(fn));
- }
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Restore aborted by user") << endl;
- return;
- }
- gettimeofday(&fend_tv, NULL);
- if (verbose > 1)
- cout << " " << cps(fileSize, &fstart_tv, &fend_tv)
- << " CPS " << endl;
- totalBytes += fileSize;
- if (res != rfsv::E_PSI_GEN_NONE) {
- if (skipError) {
- e.setName("!");
- if (verbose > 0)
- cerr << _("Skipping ") << fn << ": "
- << res << endl;
- } else {
- cerr << _("Error during restore of ") << fn << ": "
- << res << endl;
- if (isatty(0)) {
- bool askLoop = true;
- do {
- char answer;
- string vans = _("STAR");
-
- cerr << _("(S)kip all, Skip (t)his, (A)bort, (R)etry: ")
- << flush;
- cin >> answer;
- switch (vans.find(toupper(answer))) {
- case 0:
- skipError = true;
- // fall thru
- case 1:
- e.setName("!");
- askLoop = false;
- break;
- case 2:
- i = toRestore.size();
- askLoop = false;
- break;
- case 3:
- if (verbose > 1)
- cout << _("Restore ") << fn << flush;
- break;
- res = Rfsv->copyToPsion(dest.c_str(), fn, NULL, cab);
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Restore aborted by user")
- << endl;
- return;
- }
- if (verbose > 1)
- cout << endl;
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Error during restore of ")
- << fn << ": " << res << endl;
- } else
- askLoop = false;
- break;
- }
- } while (askLoop);
- } else {
- break;
- }
- }
- }
- }
- // restart previously killed programs
- startPrograms();
- gettimeofday(&end_tv, NULL);
- if (!checkAbort() && verbose > 0) {
- cout << _("Total time elapsed: ") << setprecision(4)
- << setw(6) << tdiff(&start_tv, &end_tv) << " sec." << endl;
- }
- }
-}
-
-static void
-runBackup()
-{
- vector<string>backupDrives;
- Enum<rfsv::errs> res;
- string archPath;
- bool bErr = false;
- bool found;
- int i;
- struct timeval start_tv, end_tv, cstart_tv, cend_tv, sstart_tv, send_tv;
-
- gettimeofday(&start_tv, NULL);
- if (archList.empty())
- archPath = generateBackupName();
- else
- archPath = archList[0];
-
- startMessage(archPath.c_str());
-
- // Stop all programs on Psion
- stopPrograms();
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Backup aborted by user") << endl;
- return;
- }
-
- gettimeofday(&sstart_tv, NULL);
- // Scan for files to be backed up
- backupCount = 0;
- if (driveList.empty()) {
- char drive[3];
- u_int32_t devbits;
-
- if (Rfsv->devlist(devbits) == rfsv::E_PSI_GEN_NONE) {
- for (i = 0; i < 26; i++) {
- PlpDrive psidr;
- if ((devbits & 1) && Rfsv->devinfo(i + 'A', psidr)
- == rfsv::E_PSI_GEN_NONE) {
- if (psidr.getMediaType() != 7) {
- sprintf(drive, "%c:", 'A' + i);
- if (verbose > 0)
- cout << _("Scanning Drive ") << drive << " ..."
- << flush;
- found = false;
- collectFiles(found, drive);
- if (verbose > 0)
- cout << endl;
- if (found)
- backupDrives.push_back(drive);
- }
- }
- devbits >>= 1;
- }
- } else
- cerr << _("plpbackup: Couldn't get Drive list") << endl;
- } else {
- for (i = 0; i < driveList.size(); i++) {
- char *drive = (char *)driveList[i].c_str();
- if (verbose > 0)
- cout << _("Scanning Drive ") << drive << " ..." << flush;
- found = false;
- collectFiles(found, drive);
- if (verbose > 0)
- cout << endl;
- if (found)
- backupDrives.push_back(drive);
- }
- }
- gettimeofday(&send_tv, NULL);
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Backup aborted by user") << endl;
- return;
- }
-
- // Calculate number of files and total bytecount
- for (i = 0; i < toBackup.size(); i++) {
- backupSize += toBackup[i].getSize();
- backupCount++;
- }
- if (verbose > 0)
- cout << _("Size of backup: ") << backupSize << _(" bytes in ") <<
- backupCount << _(" files.") << endl;
-
- if (backupCount == 0)
- cerr << _("Nothing to backup") << endl;
- else {
- string dest;
-
- gettimeofday(&cstart_tv, NULL);
- // copy all files
- for (i = 0; i < toBackup.size(); i++) {
- struct timeval fstart_tv, fend_tv;
- PlpDirent e = toBackup[i];
- const char *fn = e.getName();
-
- dest = archPath;
- dest += '/';
- dest += psion2unix(fn);
- fileSize = e.getSize();
- if (verbose > 1)
- cout << _("Backing up ") << fn << flush;
- if (mkdirp(dest.c_str()) != 0) {
- bErr = true;
- break;
- }
- gettimeofday(&fstart_tv, NULL);
- res = Rfsv->copyFromPsion(fn, dest.c_str(), NULL, cab);
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Backup aborted by user") << endl;
- return;
- }
- gettimeofday(&fend_tv, NULL);
- if (verbose > 1)
- cout << " "
- << cps(fileSize, &fstart_tv, &fend_tv) << " CPS" << endl;
- totalBytes += fileSize;
- if (res != rfsv::E_PSI_GEN_NONE) {
- if (skipError) {
- e.setName("!");
- if (verbose > 0)
- cerr << _("Skipping ") << fn << ": "
- << res << endl;
- } else {
- cerr << _("Error during backup of ") << fn << ": "
- << res << endl;
- if (isatty(0)) {
- bool askLoop = true;
- do {
- char answer;
- string vans = _("STAR");
-
- cerr << _("(S)kip all, Skip (t)his, (A)bort, (R)etry: ")
- << flush;
- cin >> answer;
- switch (vans.find(toupper(answer))) {
- case 0:
- skipError = true;
- // fall thru
- case 1:
- e.setName("!");
- askLoop = false;
- break;
- case 2:
- bErr = true;
- i = toBackup.size();
- askLoop = false;
- break;
- case 3:
- if (verbose > 1)
- cout << _("Backing up ") << fn << flush;
- break;
- res = Rfsv->copyFromPsion(fn, dest.c_str(), NULL, cab);
- if (checkAbort()) {
- // restart previously killed programs
- startPrograms();
- cout << _("Backup aborted by user")
- << endl;
- return;
- }
- if (verbose > 1)
- cout << endl;
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << _("Error during backup of ")
- << fn << ": " << res << endl;
- } else
- askLoop = false;
- break;
- }
- } while (askLoop);
- } else {
- bErr = true;
- break;
- }
- }
- }
- }
- gettimeofday(&cend_tv, NULL);
-
- // Create index file
- if (!bErr) {
- if (verbose > 0)
- cout << _("Writing index ...") << endl;
- dest = archPath;
- dest += "/KPsion";
- dest += ((full) ? "Full" : "Incremental");
- dest += "Index";
- ofstream op(dest.c_str());
- if (op) {
- op << "#plpbackup index " <<
- (full ? "F" : "I") << endl;
- for (i = 0; i < toBackup.size(); i++) {
- PlpDirent e = toBackup[i];
- PsiTime t = e.getPsiTime();
- long attr = e.getAttr() &
- ~rfsv::PSI_A_ARCHIVE;
- op << hex
- << setw(8) << setfill('0') <<
- t.getPsiTimeHi() << " "
- << setw(8) << setfill('0') <<
- t.getPsiTimeLo() << " "
- << setw(8) << setfill('0') <<
- e.getSize() << " "
- << setw(8) << setfill('0') <<
- attr << " "
- << setw(0) << e.getName() << endl;
- }
- op.close();
- } else {
- cerr << _("plpbackup: Could not write index ") << dest << endl;
- bErr = true;
- }
- }
-
- // finally reset archive attributes
- if (!bErr) {
- if (verbose > 0)
- cout << _("Resetting archive attributes ...") << endl;
- for (i = 0; i < toBackup.size(); i++) {
- PlpDirent e = toBackup[i];
- if (e.getAttr() & rfsv::PSI_A_ARCHIVE) {
- res = Rfsv->fsetattr(e.getName(), 0,
- rfsv::PSI_A_ARCHIVE);
- if (res != rfsv::E_PSI_GEN_NONE) {
- bErr = true;
- break;
- }
- }
- }
- }
- }
-
- if (bErr)
- cerr << _("Backup aborted due to error") << endl;
-
- // restart previously killed programs
- startPrograms();
- gettimeofday(&end_tv, NULL);
- if (!checkAbort() && verbose > 0) {
- cout << _("Total time elapsed: ") << tdiff(&start_tv, &end_tv)
- << endl;
- cout << _("Time for scanning: ") << tdiff(&sstart_tv, &send_tv)
- << endl;
- if (backupSize > 0) {
- cout << _("Time for transfer: ") << tdiff(&cstart_tv, &cend_tv)
- << endl;
- cout << _("Average transfer speed: ")
- << cps(backupSize, &cstart_tv, &cend_tv) << endl;
- }
- }
-}
-
void
-usage(ostream *hlp)
+usage(void)
{
- if (hlp == &cout) {
- *hlp <<
- _("Usage: plpbackup OPTIONS [<drive>:] [<drive>:] ...\n"
- "\n"
- " Options:\n"
- " -h, --help Print this message and exit.\n"
- " -V, --version Print version and exit.\n"
- " -p, --port=[HOST:]PORT Connect to ncpd on HOST, PORT.\n"
- " -v, --verbose Increase verbosity.\n"
- " -q, --quiet Decrease verbosity.\n"
- " -f, --full Do a full backup (incremental otherwise).\n"
- " -b, --backup[=DIR] Backup to specified directory DIR.\n"
- " -r, --restore=DIR Restore from specified directory DIR.\n"
- "\n"
- " <drive> A drive character. If none given, scan all drives.\n"
- "\n");
- exit(0);
- } else {
- *hlp << _("Try 'plpbackup --help' for more information.") << endl;
- exit(1);
- }
+ cerr <<
+ _("Usage: plpbackup OPTION...\n"
+ "\n"
+ " Options:\n"
+ " -h, --help Print this message and exit.\n"
+ " -V, --version Print version and exit.\n"
+ " -p, --port=[HOST:]PORT Connect to ncpd on HOST, PORT.\n"
+ " -v, --verbose Increase verbosity.\n"
+ " -q, --quiet Decrease verbosity.\n"
+ " --stop=FILE Stop programs and write list to FILE.\n"
+ " --start=FILE Start programs from list in FILE.\n"
+ "\n");
+ exit(0);
}
static struct option opts[] = {
- { "full", no_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ "port", required_argument, 0, 'p' },
{ "verbose", no_argument, 0, 'v' },
{ "quiet", no_argument, 0, 'q' },
- { "backup", optional_argument, 0, 'b' },
- { "restore", required_argument, 0, 'r' },
- { "version", no_argument, 0, 'V' },
+ { "stop", required_argument, 0, 1 },
+ { "start", required_argument, 0, 2 },
+ { "version", no_argument, 0, 'v' },
{ 0, 0, 0, 0 },
};
@@ -1398,6 +286,7 @@ main(int argc, char **argv)
ppsocket *skt;
ppsocket *skt2;
const char *host = "127.0.0.1";
+ char *file = NULL;
int sockNum = DPORT;
int op;
@@ -1413,61 +302,43 @@ main(int argc, char **argv)
// Command line parameter processing
opterr = 1;
- while ((op = getopt_long(argc, argv, "fFhqvVp:r:b::", opts, NULL)) != EOF) {
+ while ((op = getopt_long(argc, argv, "fFhqvVp:", opts, NULL)) != -1) {
switch (op) {
- case 'V':
- cout << _("plpbackup version ") << VERSION << endl;
- exit(0);
- case 'h':
- usage(&cout);
- break;
- case 'f':
- full = true;
- break;
- case 'v':
- verbose++;
- break;
- case 'q':
- verbose--;
- break;
- case 'b':
- doBackup = true;
- if (optarg)
- archList.push_back(optarg);
- break;
- case 'r':
- doRestore = true;
- archList.push_back(optarg);
- break;
- case 'p':
- parse_destination(optarg, &host, &sockNum);
- break;
- default:
- usage(&cerr);
- }
- }
- for (int i = optind; i < argc; i++) {
- if ((strlen(argv[i]) != 2) ||
- (toupper(argv[i][0]) < 'A') ||
- (toupper(argv[i][0]) > 'Z') ||
- (argv[i][1] != ':')) {
- cerr << _("Invalid drive argument ") << argv[i] << endl;
- usage(&cerr);
+ case 1:
+ doStop = true;
+ file = strdup(optarg);
+ break;
+ case 2:
+ doStart = true;
+ file = strdup(optarg);
+ break;
+ case 'V':
+ cerr << _("plpbackup version ") << VERSION << endl;
+ exit(0);
+ case 'h':
+ usage();
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'q':
+ verbose--;
+ break;
+ case 'p':
+ parse_destination(optarg, &host, &sockNum);
+ break;
+ default:
+ usage();
}
- driveList.push_back(argv[i]);
}
- if (doBackup && doRestore) {
- cerr << _("Backup mode can not be combined with restore.")
+ if (doStop && doStart) {
+ cerr << _("Cannot both start and stop.")
<< endl;
- usage(&cerr);
- }
- if (doBackup && (archList.size() > 1)) {
- cerr << _("Backup can only create one archive at a time.") << endl;
- usage(&cerr);
+ usage();
}
- if (!(doBackup || doRestore)) {
+ if (!(doStop || doStart)) {
cerr << _("No action specified.") << endl;
- usage(&cerr);
+ usage();
}
signal(SIGTERM, sig_handler);
@@ -1500,18 +371,10 @@ main(int argc, char **argv)
Enum<rpcs::machs> machType;
Rpcs->getMachineType(machType);
- if (machType == rpcs::PSI_MACH_S5) {
- rpcs::machineInfo mi;
- if ((res = Rpcs->getMachineInfo(mi)) ==
- rfsv::E_PSI_GEN_NONE) {
- if (!strcmp(mi.machineName, "SERIES5mx"))
- S5mx = true;
- }
- }
- if (doBackup)
- runBackup();
- if (doRestore)
- runRestore();
+ if (doStop)
+ stopPrograms(file);
+ if (doStart)
+ startPrograms(file);
delete Rpcs;
delete Rfsv;
return 0;