aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFritz Elfert <felfert@to.com>2002-02-15 09:14:22 +0000
committerFritz Elfert <felfert@to.com>2002-02-15 09:14:22 +0000
commitb3c049c98557bde9a37807bceef3040020ca787c (patch)
tree443f605a1e1110df62a4c7f318f0f4d348edbe7a
parenta15cf8adb15821a895718a85aafc3c8f06d9e6f1 (diff)
downloadplptools-b3c049c98557bde9a37807bceef3040020ca787c.tar.gz
plptools-b3c049c98557bde9a37807bceef3040020ca787c.tar.bz2
plptools-b3c049c98557bde9a37807bceef3040020ca787c.zip
- plpbackup: more error handling; translation
- Added plpprint stuff (yet not useful) - ccmalloc upgrade
-rw-r--r--Makefile.am2
-rw-r--r--acconfig.h3
-rw-r--r--configure.in47
-rw-r--r--plpbackup/Makefile.am2
-rw-r--r--plpbackup/plpbackup.cc1370
-rw-r--r--plpprint/.cvsignore5
-rw-r--r--plpprint/Makefile.am10
-rw-r--r--plpprint/plpprintd.cc310
-rw-r--r--po/POTFILES.in1
-rw-r--r--po/de.po178
10 files changed, 1393 insertions, 535 deletions
diff --git a/Makefile.am b/Makefile.am
index 5775bc3..3f9a2ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@ else
KDESUB =
endif
-SUBDIRS = intl po lib ncpd plpnfsd plpftp plpbackup $(KDESUB) doc .
+SUBDIRS = intl po lib ncpd plpnfsd plpftp plpbackup plpprint $(KDESUB) doc .
EXTRA_DIST = CHANGES COPYING README TODO INSTALL README.mjg ABOUT-NLS include/*.h* etc/*magic etc/*.in patches conf/m4/kde/*.m4 conf/m4/plptools/*.m4 conf/[a-l]* conf/missing conf/mkinstalldirs
DISTCLEANFILES = etc/psion
AUTOMAKE_OPTIONS = foreign
diff --git a/acconfig.h b/acconfig.h
index 9c2812f..9c54f24 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -72,6 +72,9 @@
/* Define this, if sys/int_types.h is on your system */
#undef HAVE_SYS_INT_TYPES_H
+/* Define this, if stdint.h is on your system */
+#undef HAVE_STDINT_H
+
/* Define this, if your int-types have an underscore after the first u/s */
#undef GNU_INTTYPES
diff --git a/configure.in b/configure.in
index 8f17acb..ecf62d4 100644
--- a/configure.in
+++ b/configure.in
@@ -2,6 +2,8 @@ AC_REVISION($Revision$)dnl revision of this configure.in script
AC_CONFIG_AUX_DIR(conf)
AC_INIT(Makefile.am)
+AC_PROG_CC
+AC_AIX
AC_CANONICAL_SYSTEM
AM_CONFIG_HEADER(include/config.h)
AM_INIT_AUTOMAKE(plptools, 0.10)
@@ -12,7 +14,6 @@ dnl Enable Maintainer stuff
AM_MAINTAINER_MODE
dnl checks for programs
-AC_AIX
AC_PROG_MAKE_SET
AC_PROG_CXX
PLP_CHECK_COMPILERS
@@ -136,46 +137,15 @@ dnl Type of sighandlers
AC_TYPE_SIGNAL
dnl checks for header files
-AC_CHECK_HEADERS(sys/time.h sys/ioctl.h sys/errno.h sys/ttold.h stdlib.h)
-
-PLP_HELP_MSG([Debugging (developer only!):])
-LIBCCMALLOC=
-AC_ARG_WITH(ccmalloc,
- [ --with-ccmalloc=DIR link against ccmalloc leak-checking lib],
- [
- search_dirs="/usr/lib /lib /usr/local/lib"
- case "${withval}" in
- yes)
- ccmalloc_dirs=${search_dirs}
- ;;
- no)
- ccmalloc_dirs=
- ;;
- *)
- ccmalloc_dirs="${withval} ${search_dirs}"
- ;;
- esac
- AC_MSG_CHECKING(for libccmalloc)
- save_LIBS="$LIBS"
- ccmalloc_found=NO
- for d in ${ccmalloc_dirs} ; do
- LIBS="-L$d -lccmalloc -ldl"
- AC_TRY_LINK_FUNC(ccmalloc_report,ccmalloc_found=$d ; break)
- done
- LIBS="$save_LIBS"
- if test "${ccmalloc_found}" = "NO" ; then
- AC_MSG_RESULT(not found)
- else
- AC_MSG_RESULT(found)
- LIBCCMALLOC="-L$ccmalloc_found -lccmalloc -ldl"
- fi
- ]
+AC_CHECK_HEADERS(
+ sys/time.h sys/ioctl.h sys/errno.h sys/ttold.h stdlib.h \
+ sys/int_types.h stdint.h
)
-AC_SUBST(LIBCCMALLOC)
+PLP_HELP_MSG([Debugging (developer only!):])
+AC_CHECK_CCMALLOC
dnl special options for customization
-
PLP_HELP_MSG([Options for overriding builtin defaults:])
AC_ARG_WITH(serial,
@@ -269,7 +239,7 @@ if test "x$ac_enable_kde" = "xyes" ; then
kde_exec_prefix=${kde_prefix}
fi
AC_ARG_WITH(kdedir,
- [ --with-kdedir=DIR specify KDE directory [\${prefix}]],
+ [ --with-kdedir=DIR specify KDE directory [${prefix:-${ac_default_prefix}}]],
[
kde_prefix=${withval}
kde_exec_prefix=${withval}
@@ -307,6 +277,7 @@ AC_OUTPUT(
kde2/doc/en/Makefile
kde2/doc/de/Makefile
plpbackup/Makefile
+ plpprint/Makefile
doc/Makefile
doc/api/Makefile
include/config.h
diff --git a/plpbackup/Makefile.am b/plpbackup/Makefile.am
index a1a859b..c868bd5 100644
--- a/plpbackup/Makefile.am
+++ b/plpbackup/Makefile.am
@@ -3,7 +3,7 @@
INCLUDES=-I$(top_srcdir)/lib
bin_PROGRAMS = plpbackup
-plpbackup_LDADD = $(top_srcdir)/lib/libplp.la
+plpbackup_LDADD = $(top_srcdir)/lib/libplp.la $(LIBCCMALLOC_CXX)
plpbackup_SOURCES = plpbackup.cc
maintainer-clean-local:
diff --git a/plpbackup/plpbackup.cc b/plpbackup/plpbackup.cc
index b10eff1..9b87024 100644
--- a/plpbackup/plpbackup.cc
+++ b/plpbackup/plpbackup.cc
@@ -1,23 +1,25 @@
-// $Id$
-//
-// plpbackup - A backup program for Psion.
-//
-// Copyright (C) 2000 Fritz Elfert <felfert@to.com>
-//
-// This program 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 of the License, or
-// (at your option) any later version.
-//
-// This program 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 this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
+/* -*- Mode: C++ -*-
+ * $Id$
+ *
+ * This file is part of plptools.
+ *
+ * Copyright (C) 2000-2001 Fritz Elfert <felfert@to.com>
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -25,525 +27,927 @@
#include <sys/types.h>
#include <dirent.h>
-#include <fstream.h>
+#include <fstream>
+#include <strstream>
+#include <iomanip>
+#include <vector>
+
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
-#include <iomanip.h>
#include <unistd.h>
+#include <signal.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#include <getopt.h>
-#include "ppsocket.h"
-#include "rfsv.h"
-#include "rfsvfactory.h"
-#include "rpcs.h"
-#include "rpcsfactory.h"
-#include "bufferstore.h"
-#include "bufferarray.h"
-#include "Enum.h"
+#include <plpintl.h>
+#include <ppsocket.h>
+#include <rfsv.h>
+#include <rfsvfactory.h>
+#include <rpcs.h>
+#include <rpcsfactory.h>
+#include <bufferstore.h>
+#include <bufferarray.h>
-void
-usage(ostream *hlp)
-{
- *hlp
- << "Usage: plpbackup OPTIONS [<drive>:] [<drive>:] ..." << endl
- << endl
- << " Options:" << endl
- << " -h, --help Print this message and exit." << endl
- << " -V, --version Print version and exit." << endl
- << " -p, --port=<port> Connect to ncpd using given port." << endl
- << " -v, --verbose Increase verbosity." << endl
- << " -q, --quiet Decrease verbosity." << endl
- << " -f, --full Do a full backup (incremental otherwise)." << endl
- << endl
- << " <drive> A drive character. If none given, scan all drives." << endl
- << endl;
-}
+bool full = false;
+bool S5mx = false;
+bool doRestore = false;
+bool doBackup = false;
+bool doFormat = false;
+bool skipError = false;
+bool doAbort = false;
-bool full;
-int verbose = 0;
-PlpDir toBackup;
+int verbose = 0;
+int caughtSig = 0;
unsigned long backupSize = 0;
+unsigned long backupCount = 0;
unsigned long totalBytes = 0;
unsigned long fileSize = 0;
-char home[1024];
+
+PlpDir toBackup;
+vector<string> driveList;
+vector<string> archList;
+vector<string> savedCommands;
+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;
+ char tstr[80];
+ static char nbuf[4096];
+
+ rpcs::machineInfo mi;
+ if ((res = Rpcs->getMachineInfo(mi)) != rfsv::E_PSI_GEN_NONE) {
+ cerr << _("Could not get machine UID") << endl;
+ exit(1);
+ }
+ strftime(tstr, sizeof(tstr), "-%Y-%m-%d-%H-%M-%S", localtime(&now));
+ sprintf(nbuf, "%s/plpbackup/%16llx/%c%s.tar.gz", getHomeDir(),
+ mi.machineUID, full ? 'F' : 'I', tstr);
+ return nbuf;
+}
+
+static const char * const
+generateTmpDir()
+{
+ char *tmpdir;
+ static char nbuf[4096];
+
+ if (!(tmpdir = getenv("TMPDIR")))
+ tmpdir = P_tmpdir;
+ sprintf(nbuf, "%s/plpbackup_%d", tmpdir, getpid());
+ mkdir(nbuf, S_IRWXU|S_IRGRP|S_IXGRP);
+ return nbuf;
+}
+
+static bool
+checkAbort()
+{
+ if (caughtSig) {
+ if (verbose > 0)
+ cout << endl;
+ cout << _("Got signal ");
+ switch (caughtSig) {
+ case SIGTERM:
+ cout << "SIGTERM";
+ break;
+ case SIGINT:
+ cout << "SIGINT";
+ break;
+ default:
+ cout << caughtSig;
+ }
+ cout << endl;
+ cout << _("Abort? (y/N) ") << flush;
+ char *validA = _("Y");
+ char answer;
+ cin >> answer;
+ caughtSig = 0;
+ if (toupper(answer) == *validA)
+ doAbort = true;
+ }
+ return doAbort;
+}
static int
-killsave(rpcs *r, bool S5mx) {
- Enum<rfsv::errs> res;
- bufferArray tmp;
- char psfile[1024];
+stopPrograms() {
+ Enum<rfsv::errs> res;
+ bufferArray tmp;
- sprintf(psfile, "%s/.plpbackup.%d", home, getpid());
- if ((res = r->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) {
+ if (verbose > 0)
+ cout << _("Stopping programs ...") << endl;
+ if ((res = Rpcs->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) {
+ cerr << _("plpbackup: Could not get process list: ") << res << endl;
+ return 1;
+ } else {
+ while (!tmp.empty()) {
+ ostrstream pbuf;
+ bufferStore cmdargs;
+ bufferStore bs = tmp.pop();
+ int pid = bs.getWord(0);
+
+ pbuf << bs.getString(2) << ".$";
+ if (S5mx)
+ pbuf << dec << setw(2) << setfill(0) << pid;
+ else
+ pbuf << dec << pid;
+ pbuf << '\0';
+ bs = tmp.pop();
+ if (Rpcs->getCmdLine(pbuf.str(), cmdargs) == 0) {
+ string cmdline = cmdargs.getString(0);
+ cmdline += " ";
+ cmdline += bs.getString(0);
+ savedCommands.push_back(cmdline);
+ if (verbose > 1)
+ cout << cmdline << endl;
+ }
+ Rpcs->stopProgram(pbuf.str());
+ }
+ time_t tstart = time(0) + 5;
+ while (true) {
+ usleep(100000);
+ if (checkAbort())
+ return 1;
+ if ((res = Rpcs->queryDrive('C', tmp)) != rfsv::E_PSI_GEN_NONE) {
cerr << "Could not get process list, Error: " << res << endl;
return 1;
- } else {
- ofstream op(psfile);
- if (!op) {
- cerr << "Could not write processlist " << psfile << endl;
- return 1;
- }
- op << "#plpbackup processlist" << endl;
- while (!tmp.empty()) {
- char pbuf[128];
- bufferStore cmdargs;
- bufferStore bs = tmp.pop();
- int pid = bs.getWord(0);
- const char *proc = bs.getString(2);
- if (S5mx)
- sprintf(pbuf, "%s.$%02d", proc, pid);
- else
- sprintf(pbuf, "%s.$%d", proc, pid);
- bs = tmp.pop();
- if (r->getCmdLine(pbuf, cmdargs) == 0)
- op << cmdargs.getString(0) << " " << bs.getString(0) << endl;
- if (verbose > 1)
- cout << cmdargs.getString(0) << " " << bs.getString(0) << endl;
- r->stopProgram(pbuf);
- }
- op.close();
+ }
+ 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;
+ cin.getline((char *)&tstart, 1);
+ tstart = time(0) + 5;
+ }
}
- return 0;
+ }
+ return 0;
}
static int
-runrestore(rfsv *a, rpcs *r) {
- Enum<rfsv::errs> res;
- bufferArray tmp;
- char psfile[1024];
-
- sprintf(psfile, "%s/.plpbackup.%d", home, getpid());
- ifstream ip(psfile);
- char cmd[512];
- char arg[512];
-
- if (!ip) {
- cerr << "Could not read processlist " << psfile << endl;
- return 1;
- }
- ip >> cmd >> arg;
+startPrograms() {
+ Enum<rfsv::errs> res;
- if (strcmp(cmd, "#plpbackup") || strcmp(arg, "processlist")) {
- ip.close();
- cerr << "Error: " << psfile <<
- " is not a process list saved with plpbackup" << endl;
- return 1;
- }
- while (!ip.eof()) {
- ip >> cmd >> arg;
- ip.get(&arg[strlen(arg)], sizeof(arg) - strlen(arg), '\n');
- if (strlen(cmd) > 0) {
- // Workaround for broken programs like Backlite. These do not store
- // the full program path. In that case we try running the arg1 which
- // results in starting the program via recog. facility.
- if (verbose > 1)
- cout << cmd << " " << arg << endl;
- if ((strlen(arg) > 2) && (arg[1] == ':') && (arg[0] >= 'A') &&
- (arg[0] <= 'Z'))
- res = r->execProgram(arg, "");
- else
- res = r->execProgram(cmd, arg);
- 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 ususal \System\Apps\<AppName>\<AppName>.app
- // on all drives.
- if (strchr(cmd, '\\') == NULL) {
- u_int32_t devbits;
- char tmp[512];
- if ((res = a->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) {
- int i;
- for (i = 0; i < 26; i++) {
- if (devbits & 1) {
- sprintf(tmp,
- "%c:\\System\\Apps\\%s\\%s.app",
- 'A' + i, cmd, cmd);
- res = r->execProgram(tmp, "");
- }
- if (res == rfsv::E_PSI_GEN_NONE)
- break;
- }
- }
- }
- }
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << "Could not start " << cmd << " " << arg << endl;
- cerr << "Error: " << res << endl;
+ if (verbose > 0)
+ cout << _("Restarting programs ...") << endl;
+ for (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);
+
+ if (!cmd.empty()) {
+ if (verbose > 1)
+ cout << cmd << " " << arg << endl;
+
+ // Workaround for broken programs like Backlite. These do not store
+ // the full program path. In that case we try running the arg1 which
+ // results in starting the program via recog. facility.
+ if ((arg.size() > 2) && (arg[1] == ':') && (arg[0] >= 'A') &&
+ (arg[0] <= 'Z'))
+ res = Rpcs->execProgram(arg.c_str(), "");
+ else
+ res = Rpcs->execProgram(cmd.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 ususal \System\Apps\<AppName>\<AppName>.app
+ // on all drives.
+ if (cmd.find('\\') == -1) {
+ u_int32_t devbits;
+ if ((res = Rfsv->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) {
+ int i;
+ for (i = 0; i < 26; i++) {
+ if (devbits & 1) {
+ ostrstream tmp;
+ tmp << 'A' + i << "\\System\\Apps\\"
+ << cmd << "\\" << cmd << ".app";
+ res = Rpcs->execProgram(tmp.str(), "");
+ }
+ if (res == rfsv::E_PSI_GEN_NONE)
+ break;
}
+ }
}
+ }
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ cerr << "Could not start " << cmd << " " << arg << endl;
+ cerr << "Error: " << res << endl;
+ }
}
- ip.close();
- unlink(psfile);
- return 0;
+ }
+ 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(rfsv *a, char *dir) {
- Enum<rfsv::errs> res;
- PlpDir files;
- char tmp[1024];
-
- strcpy(tmp, dir);
- strcat(tmp, "\\");
- if ((res = a->dir(tmp, files)) != rfsv::E_PSI_GEN_NONE)
- cerr << "Error: " << res << endl;
- else
- for (int i = 0; i < files.size(); i++) {
- PlpDirent e = files[i];
-
- // long size = s.getDWord(4);
- long attr = e.getAttr();
- strcpy(tmp, dir);
- strcat(tmp, "\\");
- strcat(tmp, e.getName());
- if (attr & rfsv::PSI_A_DIR) {
- collectFiles(a, tmp);
- } else {
- if ((attr & rfsv::PSI_A_ARCHIVE) || full) {
- e.setName(tmp);
- toBackup.push_back(e);
- }
- }
+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 (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;
- char pstr[10];
- char bstr[10];
-
- switch (verbose) {
- case -1:
- case 0:
- return 1;
- case 1:
- percent = (totalBytes + size) * 100 / backupSize;
- break;
- case 2:
- percent = size * 100 / fileSize;
- break;
- }
- sprintf(pstr, " %3d%%", percent);
- memset(bstr, 8, sizeof(bstr));
- bstr[strlen(pstr)] = '\0';
- printf("%s%s", pstr, bstr);
- fflush(stdout);
+ unsigned long percent;
+ char pstr[10];
+ char bstr[10];
+
+ if (checkAbort())
+ return 0;
+ if (verbose < 1)
return 1;
+ switch (verbose) {
+ case 1:
+ percent = (totalBytes + size) * 100 / backupSize;
+ break;
+ case 2:
+ percent = size * 100 / fileSize;
+ break;
+ }
+ sprintf(pstr, " %3d%%", percent);
+ memset(bstr, 8, sizeof(bstr));
+ bstr[strlen(pstr)] = '\0';
+ printf("%s%s", pstr, bstr);
+ fflush(stdout);
+ return 1;
}
-int
-mkdirp(char *path) {
- char *p = strchr(path, '/');
- while (p) {
- char csave = *(++p);
- *p = '\0';
- switch (mkdir(path, S_IRWXU|S_IRWXG)) {
- struct stat stbuf;
-
- case 0:
- break;
- default:
- if (errno != EEXIST) {
- perror(path);
- return 1;
- }
- stat(path, &stbuf);
- if (!S_ISDIR(stbuf.st_mode)) {
- perror(path);
- return 1;
- }
- break;
+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;
}
- *p++ = csave;
- p = strchr(p, '/');
+ break;
}
- return 0;
+ *p++ = csave;
+ p = strchr(p, '/');
+ }
+ free(path);
+ return 0;
}
-static struct option opts[] = {
- { "full", no_argument, 0, 'f' },
- { "help", no_argument, 0, 'h' },
- { "port", required_argument, 0, 'V' },
- { "verbose", no_argument, 0, 'v' },
- { "quiet", no_argument, 0, 'q' },
- { "version", no_argument, 0, 'V' },
- { 0, 0, 0, 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);
+}
-int
-main(int argc, char **argv)
+static void
+startMessage(const char *arch)
{
- ppsocket *skt;
- ppsocket *skt2;
- rfsv *a;
- rpcs *r;
- cpCallback_t cab = reportProgress;
- int status = 0;
- int sockNum = DPORT;
- int op;
- char dstPath[1024];
- struct passwd *pw;
-
- struct servent *se = getservbyname("psion", "tcp");
- endservent();
- if (se != 0L)
- sockNum = ntohs(se->s_port);
-
- // Command line parameter processing
- opterr = 1;
- while ((op = getopt_long(argc, argv, "qfhp:vV", opts, NULL)) != EOF) {
- switch (op) {
- case 'V':
- cout << "plpbackup version " << VERSION << endl;
- exit(0);
- case 'h':
- usage(&cout);
- exit(0);
- case 'f':
- full = true;
- break;
- case 'v':
- verbose++;
- break;
- case 'q':
- verbose--;
- break;
- case 'p':
- sockNum = atoi(optarg);
- break;
- default:
- usage(&cerr);
- exit(1);
+ if (verbose >= 0) {
+ cout << "Performing ";
+ if (doFormat)
+ cout << "format";
+ if (doRestore) {
+ if (doFormat)
+ cout << " and ";
+ cout << "restore";
+ } else
+ cout << (full ? "full" : "incremental") << " backup";
+ cout << " of ";
+ if (driveList.empty())
+ cout << "all drives";
+ else {
+ cout << "Drive ";
+ for (int i = 0; i < driveList.size(); i++) {
+ cout << driveList[i++];
+ if (i < (driveList.size() - 1))
+ cout << ", ";
+ else {
+ if (driveList.size() > 1)
+ cout << " and ";
}
+ }
}
- 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] != ':')) {
- usage(&cerr);
- exit(1);
- }
+ if (arch) {
+ if (doBackup)
+ cout << " to " << arch;
+ if (doRestore)
+ cout << " from " << arch;
}
+ cout << endl;
+ }
- pw = getpwuid(getuid());
- if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
- time_t now = time(0);
- char tstr[80];
- strcpy(home, pw->pw_dir);
- strftime(tstr, sizeof(tstr), "%Y-%m-%d-%H-%M-%S",
- localtime(&now));
- sprintf(dstPath, "%s/plpbackup-%s/", home, tstr);
- } else {
- cerr << "Could not get user's home directory from /etc/passwd" << endl;
- exit(-1);
- }
+}
- skt = new ppsocket();
- if (!skt->connect(NULL, sockNum)) {
- cerr << "plpbackup: could not connect to ncpd" << endl;
- return 1;
- }
- skt2 = new ppsocket();
- if (!skt2->connect(NULL, sockNum)) {
- cerr << "plpbackup: could not connect to ncpd" << endl;
- return 1;
- }
- rfsvfactory *rf = new rfsvfactory(skt);
- rpcsfactory *rp = new rpcsfactory(skt2);
- a = rf->create(false);
- r = rp->create(false);
- if ((a != NULL) && (r != NULL)) {
- Enum<rfsv::errs> res;
- Enum<rpcs::machs> machType;
- bool S5mx = false;
- bool bErr = false;
- int i;
- unsigned long backupCount = 0;
- char dest[1024];
-
- r->getMachineType(machType);
- if (machType == rpcs::PSI_MACH_S5) {
- rpcs::machineInfo mi;
- if ((res = r->getMachineInfo(mi)) == rfsv::E_PSI_GEN_NONE) {
- if (!strcmp(mi.machineName, "SERIES5mx"))
- S5mx = true;
- }
- }
- if (verbose >= 0) {
- cout << "Performing " << (full ? "full" : "incremental") <<
- " backup of ";
- if (optind < argc) {
- cout << "Drive ";
- for (i = optind; i < argc; ) {
- cout << argv[i++];
- if (i > optind) {
- if (i < (argc - 1))
- cout << ", ";
- else
- if (i < argc)
- cout << " and ";
- }
- }
- } else
- cout << "all drives";
-
- cout << " to " << dstPath << endl;
- }
- if (verbose > 0) {
- cout << "Stopping programs ..." << 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
+runFormat()
+{
+ return 0;
+}
+
+static void
+runRestore()
+{
+ int i;
+ ostrstream tarcmd;
+
+ for (i = 0; i < archList.size(); i++) {
+ tarcmd << "tar --to-stdout -xzf " << archList[i]
+ << " 'KPsion*Index'" << '\0';
+ FILE *f = popen(tarcmd.str(), "r");
+ pclose(f);
+ }
+}
+
+static void
+runBackup()
+{
+ vector<char*>backupDrives;
+ Enum<rfsv::errs> res;
+ string dstPath;
+ 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];
+ dstPath = generateTmpDir();
+
+ startMessage(archPath.c_str());
+
+ // Stop all programs on Psion
+ stopPrograms();
+ if (checkAbort()) {
+ // remove temporary dir
+ rmrf(dstPath.c_str());
+ // 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:\0", '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);
+ }
}
- killsave(r, S5mx);
- if (optind < argc) {
- for (i = optind; i < argc; i++) {
- if (verbose > 0)
- cout << "Scanning Drive " << argv[i] << " ..." << endl;
- collectFiles(a, argv[i]);
- }
+ 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()) {
+ // remove temporary dir
+ rmrf(dstPath.c_str());
+ // 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 to local temporary dir
+ for (i = 0; i < toBackup.size(); i++) {
+ PlpDirent e = toBackup[i];
+ const char *fn = e.getName();
+
+ dest = dstPath;
+ dest += '/';
+ dest += psion2unix(fn);
+ fileSize = e.getSize();
+ if (verbose > 1)
+ cout << _("Backing up ") << fn << flush;
+ if (mkdirp(dest.c_str()) != 0) {
+ bErr = true;
+ break;
+ }
+ res = Rfsv->copyFromPsion(fn, dest.c_str(), NULL, cab);
+ if (checkAbort()) {
+ // remove temporary dir
+ rmrf(dstPath.c_str());
+ // restart previously killed programs
+ startPrograms();
+ cout << _("Backup aborted by user") << endl;
+ return;
+ }
+ if (verbose > 1)
+ cout << endl;
+ totalBytes += fileSize;
+ if (res != rfsv::E_PSI_GEN_NONE) {
+ if (skipError) {
+ e.setName("!");
+ if (verbose > 0)
+ cerr << _("Skipping ") << fn << ": "
+ << res << endl;
} else {
- char drive[3];
- u_int32_t devbits;
-
- if (a->devlist(devbits) == rfsv::E_PSI_GEN_NONE) {
- for (i = 0; i < 26; i++) {
- PlpDrive psidr;
- if ((devbits & 1) && a->devinfo(i + 'A', psidr) == rfsv::E_PSI_GEN_NONE) {
- if (psidr.getMediaType() != 7) {
- sprintf(drive, "%c:\0", 'A' + i);
- if (verbose > 0)
- cout << "Scanning Drive " << drive << " ..." << endl;
- collectFiles(a, drive);
- }
- }
- devbits >>= 1;
- }
- } else
- cerr << "Couldn't get Drive list" << endl;
+ 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()) {
+ // remove temporary dir
+ rmrf(dstPath.c_str());
+ // 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 = dstPath;
+ 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++) {
- backupSize += toBackup[i].getSize();
- backupCount++;
+ 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;
}
- if (verbose > 0)
- cout << "Size of backup: " << backupSize << " bytes in " <<
- backupCount << " files." << endl;
- if (backupCount == 0)
- cerr << "Nothing to backup" << endl;
- else {
- for (i = 0; i < toBackup.size(); i++) {
- PlpDirent e = toBackup[i];
- const char *fn = e.getName();
- const char *p;
- char *q;
- char tmp[1024];
-
- for (p = fn, q = tmp; *p; p++, q++)
- switch (*p) {
- case '%':
- *q++ = '%';
- *q++ = '2';
- *q = '5';
- break;
- case '/':
- *q++ = '%';
- *q++ = '2';
- *q= 'f';
- break;
- case '\\':
- *q = '/';
- break;
- default:
- *q = *p;
- }
- *q = '\0';
- strcpy(dest, dstPath);
- strcat(dest, tmp);
- fileSize = e.getSize();
- if (verbose > 1)
- cout << "Backing up " << fn << flush;
- if (mkdirp(dest) != 0) {
- bErr = true;
- break;
- }
- res = a->copyFromPsion(fn, dest, NULL, cab);
- if (verbose > 1)
- cout << endl;
- totalBytes += fileSize;
- if (res != rfsv::E_PSI_GEN_NONE) {
- cerr << "Error during backup of " <<
- fn << ": " << res << endl;
- bErr = true;
- break;
- }
- }
- if (!bErr) {
- if (verbose > 0)
- cout << "Writing index ..." << endl;
- strcpy(dest, dstPath);
- strcat(dest, ".index");
- ofstream op(dest);
- 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 << "Could not write index " << dest << endl;
- bErr = true;
- }
- }
- 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 = a->fsetattr(e.getName(), 0,
- rfsv::PSI_A_ARCHIVE);
- if (res != rfsv::E_PSI_GEN_NONE) {
- bErr = true;
- break;
- }
- }
- }
- }
+ op.close();
+ } else {
+ cerr << _("plpbackup: Could not write index ") << dest << endl;
+ bErr = true;
+ }
+ }
+
+ // tar it all up
+ if (!bErr) {
+ ostrstream tarcmd;
+
+ if (verbose > 0)
+ cout << _("Creating tar archive ...") << endl;
+
+ tarcmd << "tar czCf";
+ if (verbose > 1)
+ tarcmd << 'v';
+ tarcmd << " " << dstPath << " " << archPath << " KPsion";
+ tarcmd << (full ? "Full" : "Incremental") << "Index";
+ for (i = 0; i < backupDrives.size(); i++)
+ tarcmd << " " << backupDrives[i];
+ tarcmd << '\0';
+
+ mkdirp(archPath.c_str());
+ if (system(tarcmd.str())) {
+ cerr << _("plpbackup: Error during execution of ")
+ << tarcmd.str() << endl;
+ unlink(archPath.c_str());
+ 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;
- if (verbose > 0)
- cout << "Restarting programs ..." << endl;
- runrestore(a, r);
- delete r;
- delete a;
- } else {
- if (!a)
- cerr << "plpbackup: could not create rfsv object" << endl;
- if (!r)
- cerr << "plpbackup: could not create rpcs object" << endl;
- exit(1);
+ }
}
- return 0;
+ }
+
+ // remove temporary dir
+ rmrf(dstPath.c_str());
+
+ 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: ")
+ << (double)backupSize / tdiff(&cstart_tv, &cend_tv) << endl;
+ }
+ }
+}
+
+void
+usage(ostream *hlp)
+{
+ 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=<port> Connect to ncpd using given port.\n"
+ " -v, --verbose Increase verbosity.\n"
+ " -q, --quiet Decrease verbosity.\n"
+ " -f, --full Do a full backup (incremental otherwise).\n"
+ " -b, --backup[=TGZ] Backup to specified archive TGZ.\n"
+ " -r, --restore=TGZ Restore from specified archive TGZ.\n"
+ " -F, --format Format drive (can be combined with restore).\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);
+ }
+}
+
+static struct option opts[] = {
+ { "full", no_argument, 0, 'f' },
+ { "help", no_argument, 0, 'h' },
+ { "port", required_argument, 0, 'V' },
+ { "verbose", no_argument, 0, 'v' },
+ { "quiet", no_argument, 0, 'q' },
+ { "backup", optional_argument, 0, 'b' },
+ { "restore", required_argument, 0, 'r' },
+ { "format", no_argument, 0, 'F' },
+ { "version", no_argument, 0, 'V' },
+ { 0, 0, 0, 0 },
+};
+
+int
+main(int argc, char **argv)
+{
+ ppsocket *skt;
+ ppsocket *skt2;
+ int sockNum = DPORT;
+ int op;
+
+ setlocale (LC_ALL, "");
+ textdomain(PACKAGE);
+
+ struct servent *se = getservbyname("psion", "tcp");
+ endservent();
+ if (se != 0L)
+ sockNum = ntohs(se->s_port);
+
+ // Command line parameter processing
+ opterr = 1;
+ while ((op = getopt_long(argc, argv, "fFhqvVp:r:b::", opts, NULL)) != EOF) {
+ 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 'F':
+ doFormat = true;
+ break;
+ case 'p':
+ sockNum = atoi(optarg);
+ 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);
+ }
+ driveList.push_back(argv[i]);
+ }
+ if (doBackup && (doRestore || doFormat)) {
+ cerr << _("Backup mode can not be combined with format or restore.")
+ << endl;
+ usage(&cerr);
+ }
+ if (doFormat && driveList.empty()) {
+ cerr << _("Format mode needs at least one drive specified.") << endl;
+ usage(&cerr);
+ }
+ if (doBackup && (archList.size() > 1)) {
+ cerr << _("Backup can only create one archive at a time.") << endl;
+ usage(&cerr);
+ }
+
+ signal(SIGTERM, sig_handler);
+ signal(SIGINT, sig_handler);
+ // Connect to Psion
+ skt = new ppsocket();
+ if (!skt->connect(NULL, sockNum)) {
+ cerr << _("plpbackup: could not connect to ncpd") << endl;
+ return 1;
+ }
+ skt2 = new ppsocket();
+ if (!skt2->connect(NULL, sockNum)) {
+ cerr << _("plpbackup: could not connect to ncpd") << endl;
+ return 1;
+ }
+ rfsvfactory *rf = new rfsvfactory(skt);
+ rpcsfactory *rp = new rpcsfactory(skt2);
+ Rfsv = rf->create(false);
+ if (Rfsv == NULL) {
+ cerr << "plpbackup: " << X_(rf->getError()) << endl;
+ exit(1);
+ }
+ Rpcs = rp->create(false);
+ if (Rpcs == NULL) {
+ cerr << "plpbackup: " << X_(rp->getError()) << endl;
+ exit(1);
+ }
+
+ Enum<rfsv::errs> res;
+ 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 (doFormat)
+ runFormat();
+ delete Rpcs;
+ delete Rfsv;
+ return 0;
}
diff --git a/plpprint/.cvsignore b/plpprint/.cvsignore
new file mode 100644
index 0000000..067f1e1
--- /dev/null
+++ b/plpprint/.cvsignore
@@ -0,0 +1,5 @@
+Makefile.in
+Makefile
+.libs
+.deps
+plpprintd
diff --git a/plpprint/Makefile.am b/plpprint/Makefile.am
new file mode 100644
index 0000000..f0d0a4e
--- /dev/null
+++ b/plpprint/Makefile.am
@@ -0,0 +1,10 @@
+# $Id$
+#
+INCLUDES=-I$(top_srcdir)/lib
+
+sbin_PROGRAMS = plpprintd
+plpprintd_LDADD = $(top_srcdir)/lib/libplp.la
+plpprintd_SOURCES = plpprintd.cc
+
+maintainer-clean-local:
+ rm -f Makefile.in
diff --git a/plpprint/plpprintd.cc b/plpprint/plpprintd.cc
new file mode 100644
index 0000000..7cf4006
--- /dev/null
+++ b/plpprint/plpprintd.cc
@@ -0,0 +1,310 @@
+/*-*-c++-*-
+ * $Id$
+ *
+ * This file is part of plptools.
+ *
+ * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stream.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <ppsocket.h>
+#include <wprt.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#define TEMPLATE "plpprint_XXXXXX"
+
+char *spooldir = "/var/spool/plpprint";
+char *printcmd = "lpr -Ppsion";
+wprt *wPrt;
+bool serviceLoop;
+bool debug = false;
+int verbose = 0;
+
+#define alloc_print(p) \
+do { \
+ /* Guess we need no more than 100 bytes. */ \
+ int n, size = 100; \
+ va_list ap; \
+ if ((p = (char *)malloc(size)) == NULL) \
+ return 0; \
+ while (1) { \
+ /* Try to print in the allocated space. */ \
+ va_start(ap, fmt); \
+ n = vsnprintf(p, size, fmt, ap); \
+ va_end(ap); \
+ /* If that worked, return the string. */ \
+ if (n > -1 && n < size) \
+ break; \
+ /* Else try again with more space. */ \
+ if (n > -1) /* glibc 2.1 */ \
+ size = n+1; /* precisely what is needed */ \
+ else /* glibc 2.0 */ \
+ size *= 2; /* twice the old size */ \
+ if ((p = (char *)realloc(p, size)) == NULL) \
+ return 0; \
+ } \
+} while (0)
+
+int
+debuglog(char *fmt, ...)
+{
+ char *buf;
+ alloc_print(buf);
+ if (debug)
+ cout << buf << endl;
+ else
+ syslog(LOG_DEBUG, buf);
+ free(buf);
+ return 0;
+}
+
+int
+errorlog(char *fmt, ...)
+{
+ char *buf;
+ alloc_print(buf);
+ if (debug)
+ cerr << buf << endl;
+ else
+ syslog(LOG_ERR, buf);
+ free(buf);
+ return 0;
+}
+
+int
+infolog(char *fmt, ...)
+{
+ char *buf;
+ alloc_print(buf);
+ if (debug)
+ cout << buf << endl;
+ else
+ syslog(LOG_INFO, buf);
+ free(buf);
+ return 0;
+}
+
+static void
+convert_job(const char *jobname)
+{
+ // ... To be done ...
+ unlink(jobname);
+}
+
+static void
+service_loop()
+{
+ serviceLoop = true;
+ while (serviceLoop) {
+ bool spoolOpen = false;
+ bufferStore c;
+ int fd;
+ char *jname =
+ (char *)malloc(strlen(spooldir) +
+ strlen(TEMPLATE) + 2);
+
+ while (1) {
+ /* Job loop */
+ c.init();
+ if (wPrt->getData(c) != rfsv::E_PSI_GEN_NONE) {
+ if (spoolOpen) {
+ unlink(jname);
+ close(fd);
+ errorlog("Job aborted");
+ }
+ free(jname);
+ return;
+ }
+ if ((c.getLen() == 15) && (c.getWord(0) == 0x2a2a)) {
+ sprintf(jname, "%s/%s", spooldir, TEMPLATE);
+ if ((fd = mkstemp(jname)) != -1) {
+ debuglog("Receiving new job %s", jname);
+ write(fd, c.getString(0), c.getLen());
+ spoolOpen = true;
+ } else
+ errorlog("Could not create spool file.");
+ } else {
+ if (spoolOpen)
+ write(fd, c.getString(0), c.getLen());
+ if (c.getWord(0) == 0xffff)
+ break;
+ }
+ }
+ if (spoolOpen) {
+ close(fd);
+ spoolOpen = false;
+ debuglog("Job received, start conversion ...");
+ convert_job(jname);
+ }
+ free(jname);
+ }
+}
+
+static void
+help() {
+ cout <<
+ "Options of plpprintd:\n"
+ "\n"
+ " -d, --debug Debugging, do not fork.\n"
+ " -h, --help Display this text.\n"
+ " -v, --verbose Increase verbosity.\n"
+ " -V, --version Print version and exit.\n"
+ " -p, --port=NUM Connect to port NUM.\n"
+ " -s, --spooldir=DIR Specify spooldir DIR.\n"
+ " -c, --printcmd=CMD Specify print command.\n";
+}
+
+static void
+usage() {
+ cerr << "Usage: plpprintd [OPTIONS]" << endl
+ << "Use --help for more information" << endl;
+}
+
+static struct option opts[] = {
+ {"debug", no_argument, 0, 'd'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {"port", required_argument, 0, 'p'},
+ {"spooldir", required_argument, 0, 's'},
+ {"printcmd", required_argument, 0, 'c'},
+ {NULL, 0, 0, 0 }
+};
+
+int
+main(int argc, char **argv)
+{
+ ppsocket *skt;
+ int status = 0;
+ int sockNum = DPORT;
+ int ret = 0;
+ int c;
+
+ struct servent *se = getservbyname("psion", "tcp");
+ endservent();
+ if (se != 0L)
+ sockNum = ntohs(se->s_port);
+
+ while (1) {
+ c = getopt_long(argc, argv, "dhVvp:s:c:", opts, NULL);
+ if (c == -1)
+ break;
+ switch (c) {
+ case '?':
+ usage();
+ return -1;
+ case 'd':
+ debug = true;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'V':
+ cout << "plpprintd Version " << VERSION << endl;
+ return 0;
+ case 'h':
+ help();
+ return 0;
+ case 'p':
+ sscanf(optarg, "%hd", &sockNum);
+ break;
+ case 's':
+ spooldir = strdup(optarg);
+ break;
+ case 'c':
+ printcmd = strdup(optarg);
+ break;
+ }
+ }
+ if (optind < argc) {
+ usage();
+ return -1;
+ }
+
+ skt = new ppsocket();
+ if (!skt->connect(NULL, sockNum)) {
+ cout << _("plpprintd: could not connect to ncpd") << endl;
+ return 1;
+ }
+ if (!debug)
+ ret = fork();
+ switch (ret) {
+ case 0:
+ /* child */
+ setsid();
+ chdir("/");
+ if (!debug) {
+ openlog("plpprintd", LOG_PID|LOG_CONS, LOG_DAEMON);
+ int devnull =
+ open("/dev/null", O_RDWR, 0);
+ if (devnull != -1) {
+ dup2(devnull, STDIN_FILENO);
+ dup2(devnull, STDOUT_FILENO);
+ dup2(devnull, STDERR_FILENO);
+ if (devnull > 2)
+ close(devnull);
+ }
+ }
+ infolog("started, waiting for requests.\n");
+ serviceLoop = true;
+ while (serviceLoop) {
+ wPrt = new wprt(skt);
+ if (wPrt) {
+ Enum<rfsv::errs> ret;
+ ret = wPrt->initPrinter();
+ if (ret == rfsv::E_PSI_GEN_NONE)
+ service_loop();
+ else
+ debuglog("plpprintd: could not connect: %s",
+ ret.toString().c_str());
+ delete wPrt;
+ } else {
+ errorlog("plpprintd: Could not create wprt object");
+ exit(1);
+ }
+ }
+ break;
+ case -1:
+ cerr << "plpprintd: fork failed" << endl;
+ return 1;
+ default:
+ /* parent */
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2beda20..d7672ba 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,3 +7,4 @@ lib/rfsvfactory.cc
plpftp/main.cc
plpftp/ftp.cc
+plpbackup/plpbackup.cc
diff --git a/po/de.po b/po/de.po
index e7a2063..c1ee92b 100644
--- a/po/de.po
+++ b/po/de.po
@@ -4,15 +4,15 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2001-05-21 17:29+0200\n"
-"PO-Revision-Date: 2001-02-28 02:44CET\n"
+"Project-Id-Version: plptools 0.11\n"
+"POT-Creation-Date: 2002-02-13 19:00+0100\n"
+"PO-Revision-Date: 2002-02-13 19:10CET\n"
"Last-Translator: Fritz Elfert <felfert@to.com>\n"
"Language-Team: Deutsch <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 0.8\n"
+"X-Generator: KBabel 0.9.5\n"
#: lib/rfsv.cc:31 lib/rfsvfactory.cc:43 lib/rpcsfactory.cc:43
msgid "no error"
@@ -296,7 +296,7 @@ msgstr "beendet"
#: lib/rfsv.cc:101
msgid "died"
-msgstr "abgestürtzt"
+msgstr "abgestürzt"
#: lib/rfsv.cc:102
msgid "bad handle"
@@ -424,7 +424,7 @@ msgstr "Schweizer Deutsch"
#: lib/rpcs.cc:75
msgid "Portugese"
-msgstr "Potugiesisch"
+msgstr "Portugiesisch"
#: lib/rpcs.cc:76
msgid "Turkish"
@@ -464,7 +464,7 @@ msgstr "Österreichisch"
#: lib/rpcs.cc:85
msgid "New Zealand"
-msgstr "Neu-Seeländisch"
+msgstr "Neuseeländisch"
#. FIXME: not shure about ISO code
#: lib/rpcs.cc:86
@@ -654,7 +654,7 @@ msgstr "Dies ist freie Software. Sie können Sie unter den Bedingungen"
#: plpftp/main.cc:59
msgid "under GPL conditions; see the COPYING file in the distribution."
-msgstr "der GPL weitergeben. Siehe die Datei COPYING im Packet."
+msgstr "der GPL weitergeben. Siehe die Datei COPYING im Paket."
#: plpftp/main.cc:61
msgid "FTP like interface started. Type \"?\" for help."
@@ -714,7 +714,7 @@ msgstr "Lokaler Ordner: \""
#: plpftp/ftp.cc:295
msgid "Psion dir: \""
-msgstr "Psion Orner: \""
+msgstr "Psion Ordner: \""
#: plpftp/ftp.cc:300 plpftp/ftp.cc:310 plpftp/ftp.cc:319 plpftp/ftp.cc:327
#: plpftp/ftp.cc:335 plpftp/ftp.cc:345 plpftp/ftp.cc:357 plpftp/ftp.cc:403
@@ -722,7 +722,7 @@ msgstr "Psion Orner: \""
#: plpftp/ftp.cc:519 plpftp/ftp.cc:545 plpftp/ftp.cc:582 plpftp/ftp.cc:610
#: plpftp/ftp.cc:671 plpftp/ftp.cc:691 plpftp/ftp.cc:698 plpftp/ftp.cc:705
#: plpftp/ftp.cc:761 plpftp/ftp.cc:771 plpftp/ftp.cc:831 plpftp/ftp.cc:873
-#: plpftp/ftp.cc:883 plpftp/ftp.cc:914 plpftp/ftp.cc:950 plpftp/ftp.cc:1006
+#: plpftp/ftp.cc:883 plpftp/ftp.cc:914 plpftp/ftp.cc:950 plpftp/ftp.cc:1016
msgid "Error: "
msgstr "Fehler: "
@@ -746,9 +746,9 @@ msgstr "Behalte ursprünglichen Ordner \""
msgid "Transfer complete, ("
msgstr "Übertragung abgeschlossen, ("
-#: plpftp/ftp.cc:537 plpftp/ftp.cc:628
+#: plpbackup/plpbackup.cc:499 plpftp/ftp.cc:537 plpftp/ftp.cc:628
msgid " bytes in "
-msgstr " bytes in "
+msgstr " Bytes in "
#: plpftp/ftp.cc:538 plpftp/ftp.cc:629
msgid " secs = "
@@ -925,3 +925,157 @@ msgstr "Kein solcher Prozess"
#: plpftp/ftp.cc:966
msgid "syntax error. Try \"help\""
msgstr "Syntaxfehler. Probieren Sie \"help\""
+
+#: plpbackup/plpbackup.cc:83
+msgid "Could not get user's home directory from /etc/passwd"
+msgstr "Konnte das persönliche Verzeichnis nicht ermitteln"
+
+#: plpbackup/plpbackup.cc:98
+msgid "Could not get machine UID"
+msgstr "Konnte Geräte-UID nicht ermitteln"
+
+#: plpbackup/plpbackup.cc:126
+msgid "Stopping programs ..."
+msgstr "Stoppe Programme ..."
+
+#: plpbackup/plpbackup.cc:128
+msgid "plpbackup: Could not get process list: "
+msgstr "plpbackup: Konnte Prozessliste nicht lesen "
+
+#: plpbackup/plpbackup.cc:162
+msgid "Restarting programs ..."
+msgstr "Starte Programme ..."
+
+#: plpbackup/plpbackup.cc:469 plpbackup/plpbackup.cc:485
+msgid "Scanning Drive "
+msgstr "Durchsuche Laufwerk "
+
+#: plpbackup/plpbackup.cc:480
+msgid "plpbackup: Couldn't get Drive list"
+msgstr "plpbackup: Konnte Laufwerks-Liste nicht ermitteln"
+
+#: plpbackup/plpbackup.cc:499
+msgid "Size of backup: "
+msgstr "Umfang der Sicherung: "
+
+#: plpbackup/plpbackup.cc:500
+msgid " files."
+msgstr " Dateien."
+
+#: plpbackup/plpbackup.cc:503
+msgid "Nothing to backup"
+msgstr "Nichts zu sichern"
+
+#: plpbackup/plpbackup.cc:518 plpbackup/plpbackup.cc:560
+msgid "Backing up "
+msgstr "Sichere "
+
+#: plpbackup/plpbackup.cc:531
+msgid "Skipping "
+msgstr "Überspringe "
+
+#: plpbackup/plpbackup.cc:534 plpbackup/plpbackup.cc:566
+msgid "Error during backup of "
+msgstr "Fehler beim Sichern von "
+
+#: plpbackup/plpbackup.cc:540
+# This are the characters for valid answers
+# of the next message.
+msgid "STAR"
+msgstr "SDAW"
+
+#: plpbackup/plpbackup.cc:542
+msgid "(S)kip all, Skip (t)his, (A)bort, (R)etry: "
+msgstr "Über(S)pringe alle, Überspringe (D)iese, (A)bbruch, (W)iederholen: "
+
+#: plpbackup/plpbackup.cc:584
+msgid "Writing index ..."
+msgstr "Schreibe Index ..."
+
+#: plpbackup/plpbackup.cc:611
+msgid "plpbackup: Could not write index "
+msgstr "plpbackup: Konnte Index nicht schreiben "
+
+#: plpbackup/plpbackup.cc:621
+msgid "Creating tar archive ..."
+msgstr "Lege tar-Archiv an ..."
+
+#: plpbackup/plpbackup.cc:631
+msgid "plpbackup: Error during execution of "
+msgstr "plpbackup: Fehler beim Ausführen von "
+
+#: plpbackup/plpbackup.cc:640
+msgid "Resetting archive attributes ..."
+msgstr "Archiv-Attribute zurücksetzen ..."
+
+#: plpbackup/plpbackup.cc:660
+msgid "Backup aborted due to error"
+msgstr "Sicherung wegen Fehler abgebrochen"
+
+#: plpbackup/plpbackup.cc:671
+msgid ""
+"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=<port> Connect to ncpd using given port.\n"
+" -v, --verbose Increase verbosity.\n"
+" -q, --quiet Decrease verbosity.\n"
+" -f, --full Do a full backup (incremental otherwise).\n"
+" -b, --backup[=TGZ] Backup to specified archive TGZ.\n"
+" -r, --restore=TGZ Restore from specified archive TGZ.\n"
+" -F, --format Format drive (can be combined with restore).\n"
+"\n"
+" <drive> A drive character. If none given, scan all drives.\n"
+"\n"
+msgstr ""
+"Benutzung: plpbackup OPTIONEN [<laufwerk>:] [<laufwerk>:] ...\n"
+"\n"
+" Optionen:\n"
+" -h, --help Anzeige dieses Textes und beenden.\n"
+" -V, --version Anzeige der Version und beenden.\n"
+" -p, --port=<port> Mit ncpd über angegebenen Port verbinden.\n"
+" -v, --verbose Ausführlichere Meldungen.\n"
+" -q, --quiet Weniger ausführliche Meldungen.\n"
+" -f, --full Komplettsicherung durchführen (andernfalls "
+"inkrementell).\n"
+" -b, --backup[=TGZ] Sicherung in das angegebene Archiv TGZ.\n"
+" -r, --restore=TGZ Rücksicherung vom angegebenen Archiv TGZ.\n"
+" -F, --format Formatiere Laufwerk (kann mit restore kombiniert "
+"werden).\n"
+"\n"
+" <laufwerk> Ein Laufwerksbuchstabe. Wird keiner angegeben, durchsuche alle "
+"Laufwerke.\n"
+"\n"
+
+#: plpbackup/plpbackup.cc:688
+msgid "Try 'plpbackup --help' for more information."
+msgstr "Versuchen Sie 'plpbackup --help' für weitere Informationen."
+
+#: plpbackup/plpbackup.cc:727
+msgid "plpbackup version "
+msgstr "plpbackup Version "
+
+#: plpbackup/plpbackup.cc:765
+msgid "Invalid drive argument "
+msgstr "Ungültiges Laufwerk "
+
+#: plpbackup/plpbackup.cc:771
+msgid "Backup mode can not be combined with format or restore."
+msgstr ""
+"Sicherungs-Modus kann nicht mit Formatieren oder Rücksicherung kombiniert "
+"werden."
+
+#: plpbackup/plpbackup.cc:776
+msgid "Format mode needs at least one drive specified."
+msgstr "Formatier-Modus benötigt mindestens eine Laufwerksangabe."
+
+#: plpbackup/plpbackup.cc:780
+msgid "Backup can only create one archive at a time."
+msgstr "Die Sicherung kann nur jeweils ein Archiv zu einer Zeit anlegen."
+
+#: plpbackup/plpbackup.cc:787 plpbackup/plpbackup.cc:792
+msgid "plpbackup: could not connect to ncpd"
+msgstr "plpbackup: Konnte ncpd nicht kontaktieren"
+