diff options
author | Fritz Elfert <felfert@to.com> | 2001-02-06 01:01:46 +0000 |
---|---|---|
committer | Fritz Elfert <felfert@to.com> | 2001-02-06 01:01:46 +0000 |
commit | a9fe8f28a4a9aaf1d9b84dbc6907849ace87f66e (patch) | |
tree | 0dd290cdf04cfd17a4ab4d0eb86bcb48137a02cb | |
parent | a8787d39b2bf1851cdea64a5e0eccc2aff7f15de (diff) | |
download | plptools-a9fe8f28a4a9aaf1d9b84dbc6907849ace87f66e.tar.gz plptools-a9fe8f28a4a9aaf1d9b84dbc6907849ace87f66e.tar.bz2 plptools-a9fe8f28a4a9aaf1d9b84dbc6907849ace87f66e.zip |
- Added KDE2 PropsDialog Plugin (incomplete)
- Fixed some KDE related autoconf stuff
- Added PlpDrive class for returning results from rfsv:devinfo
- Added auto-watch in ppsocket and finally got rid of the nasty
SIGPIPE bug. Now it's no more necessary to ignore SIGPIPE in
applications.
- Made constructors of rfsv16, rfsv32, rpcs16 and rpcs32 private to
enforce use of the factories.
- Removed error output in the factories and replaced that by error codes
which can be retrieved and evaluated by an application.
47 files changed, 1741 insertions, 194 deletions
diff --git a/Makefile.cvs b/Makefile.cvs index 753682a..9f5035e 100644 --- a/Makefile.cvs +++ b/Makefile.cvs @@ -15,13 +15,13 @@ devel: $(LIBTOOLFILES) $(AUTOMAKEFILES) touch include/stamp-h.in dist: $(LIBTOOLFILES) $(AUTOMAKEFILES) - aclocal -I conf/m4/plptools conf/m4/kde + aclocal -I conf/m4/plptools -I conf/m4/kde autoheader automake --include-deps make -C kde2 -f Makefile.am am_edit autoconf touch include/stamp-h.in - ./configure + ./configure --enable-kde $(MAKE) dist $(ACLOCAL): diff --git a/conf/m4/kde/KDE_CHECK_FINAL.m4 b/conf/m4/kde/KDE_CHECK_FINAL.m4 new file mode 100644 index 0000000..0624149 --- /dev/null +++ b/conf/m4/kde/KDE_CHECK_FINAL.m4 @@ -0,0 +1,30 @@ +AC_DEFUN(KDE_CHECK_FINAL, +[ + AC_ARG_ENABLE(final, [ --enable-final build size optimized apps (needs lots of memory)], + kde_use_final=yes, kde_use_final=no, kde_use_final=no) + + if test "x$kde_use_final" = "xyes"; then + KDE_USE_FINAL_TRUE="" + KDE_USE_FINAL_FALSE="#" + KDE_CHECK_REPO + else + KDE_USE_FINAL_TRUE="#" + KDE_USE_FINAL_FALSE="" + fi + AC_SUBST(KDE_USE_FINAL_TRUE) + AC_SUBST(KDE_USE_FINAL_FALSE) + + AC_ARG_ENABLE(closure, [ --disable-closure don't delay template instantiation], + kde_use_closure=$enableval, kde_use_closure=yes) + + if test "x$kde_use_closure" = "xyes"; then + KDE_USE_CLOSURE_TRUE="" + KDE_USE_CLOSURE_FALSE="#" +# CXXFLAGS="$CXXFLAGS $REPO" + else + KDE_USE_CLOSURE_TRUE="#" + KDE_USE_CLOSURE_FALSE="" + fi + AC_SUBST(KDE_USE_CLOSURE_TRUE) + AC_SUBST(KDE_USE_CLOSURE_FALSE) +]) diff --git a/conf/m4/plptools/PLP_CHECK_COMPILERS.m4 b/conf/m4/plptools/PLP_CHECK_COMPILERS.m4 index bd61ed2..40eb216 100644 --- a/conf/m4/plptools/PLP_CHECK_COMPILERS.m4 +++ b/conf/m4/plptools/PLP_CHECK_COMPILERS.m4 @@ -79,11 +79,13 @@ dnl this was AC_PROG_CC. I had to include it manualy, since I had to patch it if test "$ac_use_debug_code" = "no"; then if test -z "$LDFLAGS" && test "$GCC" = "yes"; then LDFLAGS="-s" + LIBDEBUG="" fi else AC_DEFINE_UNQUOTED(DEBUG) + LIBDEBUG="--debug" fi - + AC_SUBST(LIB_DEBUG) dnl this is AC_PROG_CPP. I had to include it here, since autoconf checks dnl dependecies between AC_PROG_CPP and AC_PROG_CC (or is it automake?) diff --git a/conf/m4/plptools/PLP_SET_LIBVERSION.m4 b/conf/m4/plptools/PLP_SET_LIBVERSION.m4 new file mode 100644 index 0000000..8c03f03 --- /dev/null +++ b/conf/m4/plptools/PLP_SET_LIBVERSION.m4 @@ -0,0 +1,9 @@ +AC_DEFUN(PLP_SET_LIBVERSION, + [ + AC_REQUIRE([AM_INIT_AUTOMAKE]) + maj=$(echo ${VERSION} | cut -d. -f1) + min=$(echo ${VERSION} | cut -d. -f2) + LIBVERSION=${maj}:${min}:${maj} + AC_SUBST(LIBVERSION) + ] +) diff --git a/configure.in b/configure.in index b391e48..bbe1dd5 100644 --- a/configure.in +++ b/configure.in @@ -6,6 +6,7 @@ AC_CANONICAL_SYSTEM AM_CONFIG_HEADER(include/config.h) AM_INIT_AUTOMAKE(plptools, 0.7) AM_PROG_LIBTOOL +PLP_SET_LIBVERSION dnl Enable Maintainer stuff AM_MAINTAINER_MODE @@ -214,6 +215,7 @@ PLP_HELP_MSG([Options, only needed when building KDE2 stuff:]) if test "x$ac_enable_kde" = "xyes" ; then AC_PATH_KDE AC_CHECK_KDEMAXPATHLEN + KDE_CHECK_FINAL AM_CONDITIONAL(BUILD_KDE, true) fi @@ -225,6 +227,9 @@ AC_OUTPUT( plpnfsd/Makefile kde2/Makefile kde2/kioslave/Makefile + kde2/plugins/Makefile + kde2/mime/Makefile + kde2/mime/icons/Makefile plpbackup/Makefile doc/Makefile doc/api/Makefile diff --git a/kde2/Makefile.am b/kde2/Makefile.am index fe79aad..c1186d6 100644 --- a/kde2/Makefile.am +++ b/kde2/Makefile.am @@ -1,9 +1,8 @@ # $Id$ # -SUBDIRS = kioslave +SUBDIRS = kioslave plugins mime -TMPDEST= # # remove all intermediate files that can be recreated using # Makefile.cvs diff --git a/kde2/kioslave/Makefile.am b/kde2/kioslave/Makefile.am index 1b573d9..b527f09 100644 --- a/kde2/kioslave/Makefile.am +++ b/kde2/kioslave/Makefile.am @@ -1,26 +1,18 @@ -## Makefile.am of kdebase/kioslave/plp +# $Id$ INCLUDES = $(all_includes) -I$(top_srcdir)/lib LDFLAGS = $(all_libraries) $(KDE_RPATH) -####### Files - -kio_plp_la_LDFLAGS = -module -avoid-version -no-undefined - -if BUILD_KDE - -myprotodir = $(kde_servicesdir) +kio_plp_la_LDFLAGS = -module -avoid-version lib_LTLIBRARIES = kio_plp.la kio_plp_la_SOURCES = kio_plp.cpp -kio_plp_la_LIBADD = -L$(top_srcdir)/lib -lplp -lkio -noinst_HEADERS = kio_plp.h - -myproto_DATA = psion.protocol +kio_plp_la_LIBADD = -L$(top_srcdir)/lib -lplp $(LIB_KIO) -METASOURCES = AUTO +noinst_HEADERS = kio_plp.h -bin_SCRIPTS = +services_DATA = psion.protocol +servicesdir = $(kde_servicesdir) -endif +EXTRA_DIST = $(services_DATA) diff --git a/kde2/kioslave/kio_plp.cpp b/kde2/kioslave/kio_plp.cpp index e0464bd..4b9fb49 100644 --- a/kde2/kioslave/kio_plp.cpp +++ b/kde2/kioslave/kio_plp.cpp @@ -144,14 +144,6 @@ PLPProtocol::PLPProtocol (const QCString &pool, const QCString &app) sscanf(uit.key().data(), "uid-%08X-%08X-%08X", &u1, &u2, &u3); puids.insert(PlpUID(u1, u2, u3), uit.data()); } -#if 0 - cout << "uids:" << endl; - for (UidMap::Iterator it = puids.begin(); it != puids.end(); it++) { - cout << "UID: " << hex << setw(8) << setfill('0') << it.key().uid[0] - << it.key().uid[1] << it.key().uid[2] << dec << "->" << - it.data() << endl; - } -#endif } PLPProtocol::~PLPProtocol() { @@ -218,20 +210,20 @@ openConnection() { plpRfsvSocket = new ppsocket(); if (!plpRfsvSocket->connect((char *)(currentHost.data()), currentPort)) { - error(ERR_COULD_NOT_CONNECT, i18n("Could not connect to ncpd")); + QString tmp = i18n("Could not connect to ncpd at %1:%2").arg(currentHost).arg(currentPort); + error(ERR_COULD_NOT_CONNECT, tmp); return; } rfsvfactory factory(plpRfsvSocket); plpRfsv = factory.create(false); - if (plpRfsv == 0) { - error(ERR_COULD_NOT_CONNECT, i18n("Could not read version info")); + if (plpRfsv == 0L) { + error(ERR_COULD_NOT_CONNECT, i18n("Could not read version info.")); return; } /* If we have a S5, get the Psion's Owner- and Mach- info. * This implicitely sets the Timezone info of the Psion also. */ - ppsocket rpcsSocket; if (rpcsSocket.connect((char *)(currentHost.data()), currentPort)) { rpcsfactory factory(&rpcsSocket); @@ -252,12 +244,10 @@ openConnection() { if ((res = plpRfsv->devlist(devbits)) == rfsv::E_PSI_GEN_NONE) { for (int i = 0; i < 26; i++) { - string vname; - u_int32_t vtotal, vfree, vattr, vuniqueid; - if ((devbits & 1) != 0) { - if (plpRfsv->devinfo(i, vfree, vtotal, vattr, vuniqueid, - vname) == rfsv::E_PSI_GEN_NONE) { + PlpDrive drive; + if (plpRfsv->devinfo(i, drive) == rfsv::E_PSI_GEN_NONE) { + string vname = drive.getName(); QString name; if (!vname.empty()) @@ -374,17 +364,21 @@ createVirtualDirEntry(UDSEntry & entry, bool rdonly) { atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = S_IFDIR; - entry.append( atom ); + entry.append(atom); atom.m_uds = KIO::UDS_ACCESS; atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; if (!rdonly) atom.m_long |= (S_IWUSR | S_IWGRP | S_IWOTH); - entry.append( atom ); + entry.append(atom); atom.m_uds = KIO::UDS_SIZE; atom.m_long = 0; - entry.append( atom ); + entry.append(atom); + + //atom.m_uds = KIO::UDS_MIME_TYPE; + //atom.m_str = QString("inode/x-psion-drive"); + //entry.append(atom); } bool PLPProtocol:: @@ -506,7 +500,7 @@ completeUDSEntry(UDSEntry& entry, PlpDirent &e, bool rom) { atom.m_long = (attr & rfsv::PSI_A_DIR) ? S_IFDIR : S_IFREG; entry.append(atom); -#if 1 +#if 0 KIO::UDSEntry::ConstIterator it = entry.begin(); for( ; it != entry.end(); it++ ) { switch ((*it).m_uds) { @@ -891,3 +885,68 @@ copy( const KURL &src, const KURL &dest, int _mode, bool _overwrite ) { return; finished(); } + +void PLPProtocol:: +special(const QByteArray &a) { + kdDebug(PLP_DEBUGAREA) << "special()" << endl; + + QDataStream stream(a, IO_ReadOnly); + int tmp; + UDSEntry entry; + UDSAtom atom; + + stream >> tmp; + + switch (tmp) { + case 1: { + QString param; + PlpDrive drive; + + Enum<rfsv::errs> res; + int drv; + + stream >> param; + + if (!isDrive(QString("/") + param)) { + error(ERR_PROTOCOL_IS_NOT_A_FILESYSTEM, param); + return; + } + drv = drivechars[param] - 'A'; + res = plpRfsv->devinfo(drv, drive); + if (res != rfsv::E_PSI_GEN_NONE) { + error(ERR_COULD_NOT_STAT, param); + return; + } + + string mtype; + drive.getMediaType(mtype); + + // DriveLetter + atom.m_uds = KIO::UDS_USER; + atom.m_str = QString("%1").arg(drivechars[param]); + entry.append(atom); + // TypeName + atom.m_uds = KIO::UDS_NAME; + atom.m_str = QString(mtype.c_str()); + entry.append(atom); + // Total capacity + atom.m_uds = KIO::UDS_SIZE; + atom.m_long = drive.getSize(); + entry.append(atom); + // Free capacity + atom.m_uds = KIO::UDS_MODIFICATION_TIME; + atom.m_long = drive.getSpace(); + entry.append(atom); + // UID + atom.m_uds = KIO::UDS_CREATION_TIME; + atom.m_long = drive.getUID(); + entry.append(atom); + statEntry(entry); + } + break; + default: + error(ERR_UNSUPPORTED_PROTOCOL, QString(i18n("Code: %1")).arg(tmp)); + return; + } + finished(); +} diff --git a/kde2/kioslave/kio_plp.h b/kde2/kioslave/kio_plp.h index c17436e..6768e10 100644 --- a/kde2/kioslave/kio_plp.h +++ b/kde2/kioslave/kio_plp.h @@ -52,6 +52,7 @@ public: virtual void chmod(const KURL& url, int permissions); virtual void rename(const KURL &src, const KURL &dest, bool overwrite); virtual void copy(const KURL& src, const KURL &dest, int mode, bool overwrite ); + virtual void special(const QByteArray &a); void calcprogress(long total); private: diff --git a/kde2/mime/Makefile.am b/kde2/mime/Makefile.am new file mode 100644 index 0000000..4f52cb1 --- /dev/null +++ b/kde2/mime/Makefile.am @@ -0,0 +1,27 @@ +# $Id$ +# + +SUBDIRS = icons + +EXTRA_DIST = $(wildcard *.desktop) + +maintainer-clean-local: + rm -f Makefile.in + +devmimedir = $(kde_mimedir)/inode +devmime_DATA = x-psion-drive.desktop + +appmimedir = $(kde_mimedir)/application +appmime_DATA = \ + x-psion-agenda.desktop \ + x-psion-backlite.desktop \ + x-psion-comms.desktop \ + x-psion-data.desktop \ + x-psion-encryptit.desktop \ + x-psion-opl.desktop \ + x-psion-opo.desktop \ + x-psion-record.desktop \ + x-psion-record2.desktop \ + x-psion-sheet.desktop \ + x-psion-sketch.desktop \ + x-psion-word.desktop diff --git a/kde2/mime/icons/Makefile.am b/kde2/mime/icons/Makefile.am index 2dffabc..1f5f243 100644 --- a/kde2/mime/icons/Makefile.am +++ b/kde2/mime/icons/Makefile.am @@ -5,3 +5,5 @@ maintainer-clean-local: rm -f Makefile.in KDE_ICON = AUTO + +EXTRA_DIST = $(wildcard *.png) diff --git a/kde2/mime/x-psion-drive.desktop b/kde2/mime/x-psion-drive.desktop new file mode 100644 index 0000000..d3b350c --- /dev/null +++ b/kde2/mime/x-psion-drive.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Comment=Psion Drive +Comment[de]=Psion Laufwerk +Icon=psion_drive +Type=MimeType +MimeType=inode/x-psion-drive +Patterns= diff --git a/kde2/plugins/.cvsignore b/kde2/plugins/.cvsignore new file mode 100644 index 0000000..fcada82 --- /dev/null +++ b/kde2/plugins/.cvsignore @@ -0,0 +1,4 @@ +*.closure +*.moc +Makefile.in +Makefile diff --git a/kde2/plugins/Makefile.am b/kde2/plugins/Makefile.am new file mode 100644 index 0000000..9ef736d --- /dev/null +++ b/kde2/plugins/Makefile.am @@ -0,0 +1,26 @@ + +AM_CPPFLAGS = -DQT_NO_CAST_ASCII + +INCLUDES = $(all_includes) -I$(top_srcdir)/lib +LDFLAGS = $(all_libraries) $(KDE_RPATH) + +libplpprops_la_LDFLAGS = $(LIBDEBUG) $(all_libraries) -module -no-undefined -version-info $(LIBVERSION) + +METASOURCES = AUTO + +lib_LTLIBRARIES = libplpprops.la + +libplpprops_la_SOURCES = plpprops.cc plppropsFactory.cc pie3dpiece.cpp \ + pie3dwidget.cpp +libplpprops_la_LIBADD = -L$(top_srcdir)/lib -lplp $(LIB_KIO) $(LIB_KFILE) +noinst_HEADERS = plpprops.h plppropsFactory.h pie3dpiece.h pie3dwidget.h + +services_DATA = plpprops.desktop +servicesdir = $(kde_servicesdir) + +# +# remove all intermediate files that can be recreated using +# Makefile.cvs +# +maintainer-clean-local: + rm -f Makefile.in *.closure diff --git a/kde2/plugins/pie3dpiece.cpp b/kde2/plugins/pie3dpiece.cpp new file mode 100644 index 0000000..19c98b9 --- /dev/null +++ b/kde2/plugins/pie3dpiece.cpp @@ -0,0 +1,30 @@ +/* + * This file is part of the KDE System Control Tool, + * Copyright (C)1999 Thorsten Westheider <twesthei@physik.uni-bielefeld.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ****************************************************************************/ + +#include "pie3dpiece.h" + + +Pie3DPiece::Pie3DPiece(int size, const QColor& color) : _size(size), + _color(color) +{ + +} + + diff --git a/kde2/plugins/pie3dpiece.h b/kde2/plugins/pie3dpiece.h new file mode 100644 index 0000000..b64fe2a --- /dev/null +++ b/kde2/plugins/pie3dpiece.h @@ -0,0 +1,45 @@ +/* + * This file is part of the KDE System Control Tool, + * Copyright (C)1999 Thorsten Westheider <twesthei@physik.uni-bielefeld.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + ****************************************************************************/ + +#ifndef __PIE3DPIECE_H +#define __PIE3DPIECE_H + +#include <qcolor.h> + + +class Pie3DPiece +{ + public: + + Pie3DPiece(int size, const QColor&); + Pie3DPiece() {} + + int size() const { return _size; } + const QColor& color() const { return _color; } + + private: + + int _size; + QColor _color; +}; + + +#endif + diff --git a/kde2/plugins/pie3dwidget.cpp b/kde2/plugins/pie3dwidget.cpp new file mode 100644 index 0000000..72a4578 --- /dev/null +++ b/kde2/plugins/pie3dwidget.cpp @@ -0,0 +1,120 @@ +/* + * This file is part of the KDE System Control Tool, + * Copyright (C)1999 Thorsten Westheider <twesthei@physik.uni-bielefeld.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Pie3DWidget was inspired by Christian Poulter's KDiskFree + * + ****************************************************************************/ + +#include <qpainter.h> + +#include "pie3dwidget.h" + + +Pie3DWidget::Pie3DWidget(QWidget *parent, const char *name) : QWidget(parent, name), + _totalsize(0) +{ + _piecelist.setAutoDelete(true); + _piecelist.clear(); +} + + +void Pie3DWidget::addPiece(int size, const QColor& color) +{ + _totalsize += size; + + _piecelist.append(new Pie3DPiece(size, color)); + + repaint(); +} + + +int Pie3DWidget::heightForWidth(int w) const +{ + return (int) (w*0.6); +} + + +QSize Pie3DWidget::minimumSizeHint() const +{ + return QSize(60, 40); +} + + +QSize Pie3DWidget::sizeHint() const +{ + return QSize(width(), width()*0.6); +} + + +/* + * Protected methods + ********************/ + +void Pie3DWidget::paintEvent(QPaintEvent *ev) +{ + QPainter p; + QColor widgetbg = palette().normal().background(); + QColor black = QColor(black); + int w = width(); + int h = height(); + int pieh = h/4; + int halfrot = 180*16; + int fullrot = 360*16; + int bowpos = 0; + int i, bowlen, bowcut; + + if (_piecelist.isEmpty()) return; + + p.begin(this); + p.setClipRegion(ev->region()); + + for (Pie3DPiece *piece = _piecelist.first(); piece; piece = _piecelist.next()) + { + QPalette piecepal(piece->color(), widgetbg); + + bowlen = (int) (((double) piece->size())/_totalsize*fullrot); + + p.setPen((_piecelist.count() > 1) ? black : _piecelist.first()->color()); + p.setBrush(piecepal.normal().button()); + p.drawPie(0, 0, w, h-pieh, bowpos, bowlen); + + if (bowpos+bowlen >= halfrot) // Part of the footer is visible + { + bowcut = (bowpos < halfrot) ? halfrot-bowpos : 0; + bowpos += bowcut; + bowlen -= bowcut; + + p.setPen(piecepal.normal().mid()); + + for (i = 0; i < pieh; i++) p.drawArc(0, i, w, h-pieh, bowpos, bowlen); + } + + bowpos += bowlen; + } + + p.setPen(black); + + p.drawArc(0, 0, w, h-pieh, 0, fullrot); + p.drawArc(0, pieh-1, w, h-pieh, 0, -halfrot); + + p.drawLine(0, (h-pieh)/2, 0, (h+pieh)/2-1); + p.drawLine(w-1, (h-pieh)/2, w-1, (h+pieh)/2-1); + + p.end(); +} + diff --git a/kde2/plugins/pie3dwidget.h b/kde2/plugins/pie3dwidget.h new file mode 100644 index 0000000..cda0868 --- /dev/null +++ b/kde2/plugins/pie3dwidget.h @@ -0,0 +1,56 @@ +/* + * This file is part of the KDE System Control Tool, + * Copyright (C)1999 Thorsten Westheider <twesthei@physik.uni-bielefeld.de> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Pie3DWidget was inspired by Christian Poulter's KDiskFree + * + ****************************************************************************/ + +#ifndef __PIE3DWIDGET_H +#define __PIE3DWIDGET_H + +#include <qwidget.h> +#include <qlist.h> + +#include "pie3dpiece.h" + + +class Pie3DWidget : public QWidget +{ + public: + + Pie3DWidget(QWidget *parent = 0L, const char *name = 0L); + ~Pie3DWidget() {} + + void addPiece(int size, const QColor&); + + virtual int heightForWidth(int w) const; + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + + protected: + + virtual void paintEvent(QPaintEvent *); + + private: + + int _totalsize; + QList<Pie3DPiece> _piecelist; +}; + + +#endif diff --git a/kde2/plugins/plpprops.cc b/kde2/plugins/plpprops.cc new file mode 100644 index 0000000..bd4a2f5 --- /dev/null +++ b/kde2/plugins/plpprops.cc @@ -0,0 +1,441 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stream.h> +#include <errno.h> +#include <assert.h> + +#include <qfile.h> +#include <qapplication.h> +#include <qdir.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qstrlist.h> +#include <qstringlist.h> +#include <qtextstream.h> +#include <qpainter.h> +#include <qlayout.h> +#include <qcombobox.h> +#include <qgroupbox.h> + +#include <kdialog.h> +#include <kdirsize.h> +#include <kdirwatch.h> +#include <kdebug.h> +#include <kdesktopfile.h> +#include <kicondialog.h> +#include <kurl.h> +#include <kurlrequester.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kstddirs.h> +#include <kio/job.h> +#include <kio/renamedlg.h> +#include <kfiledialog.h> +#include <kmimetype.h> +#include <kmessagebox.h> +#include <kservice.h> +#include <kglobal.h> +#include <kcompletion.h> +#include <klineedit.h> +//#include <klibloader.h> +//#include <ktrader.h> +#include <kio/slaveinterface.h> + +#include "plpprops.h" +#include "pie3dwidget.h" + +#include <qobjectlist.h> +#include <qtabwidget.h> + +#define KIO_ARGS QByteArray packedArgs; \ +QDataStream stream( packedArgs, IO_WriteOnly ); stream + +class PlpPropsPlugin::PlpPropsPluginPrivate { +public: + PlpPropsPluginPrivate() { } + ~PlpPropsPluginPrivate() { } + + QFrame *m_frame; +}; + +/* + * A VERY UGLY HACK for removing the Permissions-Page from + * the Properties dialog. + */ +static void +removePermsPage(QWidget *theDialog) { + QObject *qtabwidget = 0L; + QFrame *permframe = 0L; + + // + // First, find the QTabWidget in the dialog. + // This is easy, cause there's only one. + // + QObjectList *l = theDialog->queryList("QTabWidget"); + QObjectListIt it(*l); + QObject * obj; + while ((obj=it.current()) != 0) { + ++it; + qtabwidget = obj; + } + delete l; + + // Now, walk thru all Childs of the QTabWidget which are + // inherited from class QFrame. + // + if (qtabwidget != 0L) { + l = qtabwidget->queryList("QFrame"); + QObjectListIt it(*l); + + while ((obj = it.current()) != 0) { + QObjectList *l2 = obj->queryList(); + QObjectListIt it2(*l2); + QObject *o2; + int qvbl, qgb, qgl, ql, qcb; + qvbl = qgb = qgl = ql = qcb = 0; + + // If we found a QFrame, count it's children + // by className. We must rely on the numbers, + // because not a single child has been given + // a name. + while ((o2 = it2.current()) != 0) { + if (o2->isA("QVBoxLayout")) + qvbl++; + if (o2->isA("QGroupBox")) + qgb++; + if (o2->isA("QGridLayout")) + qgl++; + if (o2->isA("QLabel")) + ql++; + if (o2->isA("QCheckBox")) + qcb++; + ++it2; + } + delete l2; + + // The PermissionsPage is build out of: + // + // 1 QVBoxLayout, 2 QGroupboxes, 2 QGridLayouts, + // 15 QLabels and 12 QCheckBoxes + // + if ((qvbl == 1) && + (qgb == 2) && + (qgl == 2) && + (ql == 15) && + (qcb == 12)) { + permframe = (QFrame *)obj; + break; + } + ++it; + } + delete l; + + // If we found it, remove it. + if (permframe != 0) + ((QTabWidget *)qtabwidget)->removePage(permframe); + } +} + +PlpPropsPlugin::PlpPropsPlugin(KPropertiesDialog *_props) + : KPropsDlgPlugin( _props ) +{ + d = new PlpPropsPluginPrivate; + bool removePerms = false; + + if (!supports(properties->items())) + return; + + if (PlpFileAttrPage::supports(properties->items())) { + PlpFileAttrPage *p = new PlpFileAttrPage(_props); + removePerms = true; + } + if (PlpDriveAttrPage::supports(properties->items())) { + PlpDriveAttrPage *p = new PlpDriveAttrPage(_props); + removePerms = true; + } + if (PlpMachinePage::supports(properties->items())) { + PlpMachinePage *p = new PlpMachinePage(_props); + } + if (PlpOwnerPage::supports(properties->items())) { + PlpOwnerPage *p = new PlpOwnerPage(_props); + } + if (removePerms) + removePermsPage(properties->dialog()); +} + +PlpPropsPlugin::~PlpPropsPlugin() { + delete d; +} + +bool PlpPropsPlugin::supports(KFileItemList _items) { + for (KFileItemListIterator it(_items); it.current(); ++it) { + KFileItem *fi = it.current(); + + if (fi->url().protocol() != QString::fromLatin1("psion")) + return false; + } + return true; +} + +void PlpPropsPlugin::applyChanges() { + kdDebug(250) << "PlpFileAttrPlugin::applyChanges" << endl; +} + +void PlpPropsPlugin::postApplyChanges() { +} + +class PlpFileAttrPage::PlpFileAttrPagePrivate { +public: + PlpFileAttrPagePrivate() { } + ~PlpFileAttrPagePrivate() { } + + QFrame *m_frame; +}; + +PlpFileAttrPage::PlpFileAttrPage(KPropertiesDialog *_props) + : KPropsDlgPlugin( _props ) { + d = new PlpFileAttrPagePrivate; + d->m_frame = properties->dialog()->addPage(i18n("Psion &Attributes")); +} + +PlpFileAttrPage::~PlpFileAttrPage() { + delete d; +} + +bool PlpFileAttrPage::supports(KFileItemList _items) { + for (KFileItemListIterator it(_items); it.current(); ++it) { + KFileItem *fi = it.current(); + + QString path = fi->url().path(-1); + if (path.contains('/') == 1) + return false; + } + return true; +} + +void PlpFileAttrPage::applyChanges() { +} + +class PlpDriveAttrPage::PlpDriveAttrPagePrivate { +public: + PlpDriveAttrPagePrivate() { } + ~PlpDriveAttrPagePrivate() { } + + QFrame *m_frame; +}; + +PlpDriveAttrPage::PlpDriveAttrPage(KPropertiesDialog *_props) + : KPropsDlgPlugin( _props ) { + + d = new PlpDriveAttrPagePrivate; + d->m_frame = properties->dialog()->addPage(i18n("Psion &Drive")); + + QBoxLayout *box = new QVBoxLayout( d->m_frame, KDialog::spacingHint() ); + QLabel *l; + QGridLayout *gl; + + KIO_ARGS << int(1) << properties->item()->name(); + KIO::StatJob *job = new KIO::StatJob(KURL("psion:/"), KIO::CMD_SPECIAL, packedArgs, false); + connect(job, SIGNAL(result(KIO::Job *)), SLOT(slotSpecialFinished(KIO::Job *))); + + + long total = 33267; + long free = 12345; + + gb = new QGroupBox(i18n("Information"), d->m_frame); + box->addWidget(gb); + + gl = new QGridLayout(gb, 7, 4, 15); + gl->addRowSpacing(0, 10); + + l = new QLabel(i18n("Type"), gb); + gl->addWidget(l, 1, 0); + + typeLabel = new QLabel(gb); + gl->addWidget(typeLabel, 2, 0); + + l = new QLabel(i18n("Total capacity"), gb); + gl->addWidget (l, 1, 1); + + totalLabel = new QLabel(gb); + gl->addWidget(totalLabel, 2, 1); + + l = new QLabel(i18n("Free space"), gb); + gl->addWidget (l, 1, 2); + + freeLabel = new QLabel(gb); + gl->addWidget(freeLabel, 2, 2); + + l = new QLabel(i18n("Unique ID"), gb); + gl->addWidget (l, 1, 3); + + uidLabel = new QLabel(gb); + gl->addWidget(uidLabel, 2, 3); + + pie = new Pie3DWidget(gb, "pie"); + + gl->addMultiCellWidget(pie, 3, 4, 1, 2); + + l = new QLabel(i18n("Used space"), gb); + gl->addWidget (l, 5, 2); + + l = new QLabel(i18n(" "), gb); + l->setBackgroundColor(QColor(219, 58, 197)); + gl->addWidget (l, 5, 3); + + l = new QLabel(i18n("Free space"), gb); + gl->addWidget (l, 6, 2); + + l = new QLabel(i18n(" "), gb); + l->setBackgroundColor(QColor(39, 56, 167)); + + gl->addWidget (l, 6, 3); + + box->addStretch(10); +} + +PlpDriveAttrPage::~PlpDriveAttrPage() { + delete d; +} + +bool PlpDriveAttrPage::supports(KFileItemList _items) { + for (KFileItemListIterator it(_items); it.current(); ++it) { + KFileItem *fi = it.current(); + + QString path = fi->url().path(-1); + if (path.contains('/') != 1) + return false; + } + return true; +} + +void PlpDriveAttrPage::applyChanges() { +} + +void PlpDriveAttrPage::slotSpecialFinished(KIO::Job *job) { + KIO::StatJob *sJob = static_cast<KIO::StatJob *>(job); + + if (sJob->error()) + job->showErrorDialog(properties->dialog()); + else { + KIO::UDSEntry e = sJob->statResult(); + bool total_found = false; + bool free_found = false; + + for (KIO::UDSEntry::ConstIterator it = e.begin(); it != e.end(); ++it) { + if ((*it).m_uds == KIO::UDS_SIZE) { + total_found = true; + total = (unsigned long)((*it).m_long); + } + if ((*it).m_uds == KIO::UDS_MODIFICATION_TIME) { + free_found = true; + unused = (unsigned long)((*it).m_long); + } + if ((*it).m_uds == KIO::UDS_CREATION_TIME) { + unsigned long uid = (unsigned long)((*it).m_long); + uidLabel->setText(QString::fromLatin1("%1").arg(uid, 8, 16)); + } + if ((*it).m_uds == KIO::UDS_NAME) { + QString name = ((*it).m_str); + typeLabel->setText(name); + } + if ((*it).m_uds == KIO::UDS_USER) { + QString name = ((*it).m_str); + gb->setTitle(QString(i18n("Information for Psion drive %1: (%2)")).arg(name).arg(properties->item()->name())); + } + } + if (total_found && free_found) { + totalLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(total)).arg(KGlobal::locale()->formatNumber(total, 0))); + freeLabel->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(unused)).arg(KGlobal::locale()->formatNumber(unused, 0))); + pie->addPiece(total - unused, QColor(219, 58, 197)); + pie->addPiece(unused, QColor(39, 56, 167)); + } + } +} + +class PlpMachinePage::PlpMachinePagePrivate { +public: + PlpMachinePagePrivate() { } + ~PlpMachinePagePrivate() { } + + QFrame *m_frame; +}; + +PlpMachinePage::PlpMachinePage( KPropertiesDialog *_props ) + : KPropsDlgPlugin( _props ) { + + d = new PlpMachinePagePrivate; + d->m_frame = properties->dialog()->addPage(i18n("Psion &Machine")); + + QVBoxLayout * mainlayout = new QVBoxLayout( d->m_frame, KDialog::spacingHint()); + + // Now the widgets in the top layout + + QLabel* l; + l = new QLabel(d->m_frame, "Label_1" ); + l->setText( i18n("Machine UID:") ); + mainlayout->addWidget(l, 1); + + mainlayout->addStretch(2); +} + +PlpMachinePage::~PlpMachinePage() { + delete d; +} + +bool PlpMachinePage::supports(KFileItemList _items) { + for (KFileItemListIterator it(_items); it.current(); ++it) { + KFileItem *fi = it.current(); + + QString path = fi->url().path(-1); + if (path.contains('/') != 1) + return false; + if (fi->mimetype() != QString::fromLatin1("application/x-psion-machine")) + return false; + } + return true; +} + +void PlpMachinePage::applyChanges() { +} + + +class PlpOwnerPage::PlpOwnerPagePrivate +{ +public: + PlpOwnerPagePrivate() { } + ~PlpOwnerPagePrivate() { } + + QFrame *m_frame; +}; + +PlpOwnerPage::PlpOwnerPage( KPropertiesDialog *_props ) : KPropsDlgPlugin( _props ) { + d = new PlpOwnerPagePrivate; + d->m_frame = properties->dialog()->addPage(i18n("Psion &Owner")); +} + +PlpOwnerPage::~PlpOwnerPage() { + delete d; +} + +bool PlpOwnerPage::supports(KFileItemList _items) { + for (KFileItemListIterator it(_items); it.current(); ++it) { + KFileItem *fi = it.current(); + + QString path = fi->url().path(-1); + if (path.contains('/') != 1) + return false; + if (fi->mimetype() != QString::fromLatin1("application/x-psion-owner")) + return false; + } + return true; +} + +void PlpOwnerPage::applyChanges() { +} + +#include "plpprops.moc" diff --git a/kde2/plugins/plpprops.desktop b/kde2/plugins/plpprops.desktop new file mode 100644 index 0000000..9fc8b2f --- /dev/null +++ b/kde2/plugins/plpprops.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Type=Service +X-KDE-Library=libplpprops +Name=Psion Property Dialog Plugin +ServiceTypes=KPropsDlg/Plugin,all/all +Comment=Plugin for the Properties Dialog +Comment[ca]=Endollat pel diàleg de propietats +Comment[cs]=Modul pro dialog vlastností +Comment[da]=Plugin til egenskabsdialog +Comment[de]=Plugin für den Eigenschaften-Dialog +Comment[el]=Πρόσθετο για το Διάλογο Ιδιοτήτων +Comment[eo]=Internaĵo por la Eco-dialogo +Comment[es]=Plugin para el Diálogo de Propiedades +Comment[et]=Plugina omaduste dialoog +Comment[fi]=Sovelma asetusikkunalle +Comment[fr]=Module pour la boîte de dialogue des Propriétés +Comment[gl]=Plugin para o Diálogo de Propiedades +Comment[he]=םינייפאמה חיש-ודל עקת ןקתה +Comment[hu]=Beépülő modul a tulajdonságok párbeszédablakhoz +Comment[is]=Íhlutur fyrir stillingarforritið +Comment[it]=Plugin per la finestra delle proprietà +Comment[ja]=設定ダイアログプラグイン +Comment[mk]=Плагин за дијалогот за параметри +Comment[nl]=Plugin voor het 'Eigenschappen'dialoog +Comment[no]=Plugginn for egenskaper-dialogen +Comment[no_NY]=Tillegg til eigenskapar-dialogen +Comment[pl]=Wtyczka do Dialogu Właściwości +Comment[pt]='Plugin' para o diálogo de propriedades +Comment[pt_BR]=Plug-in para a janela de Propriedades +Comment[ro]=Modul pentru dialogul de proprietăţi +Comment[ru]=Модуль для диалога настроек +Comment[sk]=Zásuvný modul pre panel Nastavení +Comment[sl]=Vstavek za pogovorno okno z lastnostmi +Comment[sr]=Plugin za dijalog sa svojstvima +Comment[sv]=Insticksprogram för egenskapsdialogen +Comment[ta]=¦º¡òÐì¸û ¯¨Ã¡¼Öì¸¡É ¦ºÕ¸ø +Comment[tr]=Özellikler İletişim Kutusu İçin Eklenti +Comment[uk]=Додаток для діалогу властивостей +Comment[zh_CN.GB2312]=属性对话的插件 +Comment[zh_TW.Big5]=外掛內容對話框 diff --git a/kde2/plugins/plpprops.h b/kde2/plugins/plpprops.h new file mode 100644 index 0000000..86f3514 --- /dev/null +++ b/kde2/plugins/plpprops.h @@ -0,0 +1,144 @@ +/* $Id$ + * + * This file holds the definitions for all classes used to + * display a Psion related properties dialog. + */ + +#ifndef _PLPPROPS_H_ +#define _PLPPROPS_H_ + +#include <qstring.h> +#include <qlist.h> +#include <qgroupbox.h> + +#include <kurl.h> +#include <kfileitem.h> +#include <kdialogbase.h> +#include <kpropsdlg.h> + +#include "pie3dwidget.h" + +namespace KIO { class Job; } + +class PlpPropsPlugin : public KPropsDlgPlugin { + Q_OBJECT + public: + /** + * Constructor + */ + PlpPropsPlugin( KPropertiesDialog *_props ); + virtual ~PlpPropsPlugin(); + + /** + * Applies all changes made. + */ + virtual void applyChanges(); + + /** + * Tests whether the files specified by _items need a 'General' plugin. + */ + static bool supports(KFileItemList _items); + + /** + * Called after all plugins applied their changes + */ + void postApplyChanges(); + + private: + class PlpPropsPluginPrivate; + PlpPropsPluginPrivate *d; +}; + +class PlpFileAttrPage : public KPropsDlgPlugin { + Q_OBJECT + public: + /** + * Constructor + */ + PlpFileAttrPage(KPropertiesDialog *_props); + virtual ~PlpFileAttrPage(); + + virtual void applyChanges(); + + static bool supports(KFileItemList _items); + + private: + class PlpFileAttrPagePrivate; + PlpFileAttrPagePrivate *d; +}; + +class PlpDriveAttrPage : public KPropsDlgPlugin { + Q_OBJECT + public: + /** + * Constructor + */ + PlpDriveAttrPage(KPropertiesDialog *_props); + virtual ~PlpDriveAttrPage(); + + virtual void applyChanges(); + + static bool supports(KFileItemList _items); + + private slots: + void slotSpecialFinished(KIO::Job *job); + + private: + class PlpDriveAttrPagePrivate; + PlpDriveAttrPagePrivate *d; + + unsigned long total; + unsigned long unused; + + QGroupBox *gb; + QLabel *uidLabel; + QLabel *typeLabel; + QLabel *totalLabel; + QLabel *freeLabel; + Pie3DWidget *pie; +}; + + +/** + * Used to view/edit machine info. + */ +class PlpMachinePage : public KPropsDlgPlugin { + Q_OBJECT + public: + /** + * Constructor + */ + PlpMachinePage(KPropertiesDialog *_props); + virtual ~PlpMachinePage(); + + virtual void applyChanges(); + + static bool supports(KFileItemList _items); + + private: + class PlpMachinePagePrivate; + PlpMachinePagePrivate *d; +}; + +/** + * Used to view/edit owner info + */ +class PlpOwnerPage : public KPropsDlgPlugin { + Q_OBJECT + public: + /** + * Constructor + */ + PlpOwnerPage(KPropertiesDialog *_props); + virtual ~PlpOwnerPage(); + + virtual void applyChanges(); + + static bool supports(KFileItemList _items); + + private: + class PlpOwnerPagePrivate; + PlpOwnerPagePrivate *d; +}; + +#endif diff --git a/kde2/plugins/plppropsFactory.cc b/kde2/plugins/plppropsFactory.cc new file mode 100644 index 0000000..2c553cf --- /dev/null +++ b/kde2/plugins/plppropsFactory.cc @@ -0,0 +1,37 @@ +#include "plppropsFactory.h" +#include "plpprops.h" + +#include <stream.h> +#include <kdebug.h> +#include <klocale.h> + +extern "C" { + void *init_libplpprops() { + return new plppropsFactory(); + } +}; + +plppropsFactory::plppropsFactory(QObject *parent, const char *name) + : KLibFactory(parent, name) { + s_global = new KInstance("plpprops"); + // Install the translations + //KGlobal::locale()->insertCatalogue("plpprops"); +} + +plppropsFactory::~plppropsFactory() { + delete s_global; +} + +QObject* plppropsFactory::createObject(QObject* parent, const char *name, const char *classname, const QStringList & ) { + + QObject *obj = 0L; + + cout << "plppropsFactory: name=" << name << " class=" << classname << endl; + if ((strcmp(classname, "KPropsDlgPlugin") == 0) && + parent && + parent->inherits("KPropertiesDialog")) + obj = new PlpPropsPlugin(static_cast<KPropertiesDialog *>(parent)); + return obj; +} + +#include <plppropsFactory.moc> diff --git a/kde2/plugins/plppropsFactory.h b/kde2/plugins/plppropsFactory.h new file mode 100644 index 0000000..1226560 --- /dev/null +++ b/kde2/plugins/plppropsFactory.h @@ -0,0 +1,19 @@ +#ifndef _PLPPROPSFACTORY_H_ +#define _PLPPROPSFACTORY_H_ + +#include <klibloader.h> + +class plppropsFactory : public KLibFactory { + Q_OBJECT + public: + plppropsFactory(QObject *parent = 0, const char *name = 0); + virtual ~plppropsFactory(); + + virtual QObject* createObject(QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList()); + + private: + KInstance *s_global; + +}; + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am index 367fbb7..7e56949 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,7 +2,8 @@ # lib_LTLIBRARIES = libplp.la -libplp_la_LDFLAGS = --debug -version-info 1:1:0 +libplp_la_LDFLAGS = $(LIBDEBUG) -version-info $(LIBVERSION) + libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc \ rfsv16.cc rfsv32.cc rfsvfactory.cc log.cc rfsv.cc rpcs32.cc rpcs16.cc \ rpcs.cc rpcsfactory.cc psitime.cc Enum.cc plpdirent.cc diff --git a/lib/plpdirent.cc b/lib/plpdirent.cc index 33e1a78..9695480 100644 --- a/lib/plpdirent.cc +++ b/lib/plpdirent.cc @@ -83,3 +83,141 @@ operator<<(ostream &o, const PlpDirent &e) { o.flags(old); return o; } + +PlpDrive::PlpDrive() { +} + +PlpDrive::PlpDrive(const PlpDrive &other) { +} + +void PlpDrive:: +setMediaType(u_int32_t type) { + mediatype = type; +} + +void PlpDrive:: +setDriveAttribute(u_int32_t attr) { + driveattr = attr; +} + +void PlpDrive:: +setMediaAttribute(u_int32_t attr) { + mediaattr = attr; +} + +void PlpDrive:: +setUID(u_int32_t attr) { + uid = attr; +} + +void PlpDrive:: +setSize(u_int32_t sizeLo, u_int32_t sizeHi) { + size = ((unsigned long long)sizeHi << 32) + sizeLo; +} + +void PlpDrive:: +setSpace(u_int32_t spaceLo, u_int32_t spaceHi) { + space = ((unsigned long long)spaceHi << 32) + spaceLo; +} + +void PlpDrive:: +setName(char drive, const char * const volname) { + drivechar = drive; + name = ""; + name += volname; +} + +u_int32_t PlpDrive:: +getMediaType() { + return mediatype; +} + +static const char * const media_types[] = { + "Not present", + "Unknown", + "Floppy", + "Disk", + "CD-ROM", + "RAM", + "Flash Disk", + "ROM", + "Remote", +}; + +void PlpDrive:: +getMediaType(string &ret) { + ret = media_types[mediatype]; +} + +u_int32_t PlpDrive:: +getDriveAttribute() { + return driveattr; +} + +static void +appendWithDelim(string &s1, const char * const s2) { + if (!s1.empty()) + s1 += ','; + s1 += s2; +} + +void PlpDrive:: +getDriveAttribute(string &ret) { + ret = ""; + if (driveattr & 1) + appendWithDelim(ret, "local"); + if (driveattr & 2) + appendWithDelim(ret, "ROM"); + if (driveattr & 4) + appendWithDelim(ret, "redirected"); + if (driveattr & 8) + appendWithDelim(ret, "substituted"); + if (driveattr & 16) + appendWithDelim(ret, "internal"); + if (driveattr & 32) + appendWithDelim(ret, "removable"); +} + +u_int32_t PlpDrive:: +getMediaAttribute() { + return mediaattr; +} + +void PlpDrive:: +getMediaAttribute(string &ret) { + ret = ""; + + if (mediaattr & 1) + appendWithDelim(ret, "variable size"); + if (mediaattr & 2) + appendWithDelim(ret, "dual density"); + if (mediaattr & 4) + appendWithDelim(ret, "formattable"); + if (mediaattr & 8) + appendWithDelim(ret, "write protected"); +} + +u_int32_t PlpDrive:: +getUID() { + return uid; +} + +u_int64_t PlpDrive:: +getSize() { + return size; +} + +u_int64_t PlpDrive:: +getSpace() { + return space; +} + +string PlpDrive:: +getName() { + return name; +} + +char PlpDrive:: +getDrivechar() { + return drivechar; +} diff --git a/lib/plpdirent.h b/lib/plpdirent.h index 9a25a67..c567a9b 100644 --- a/lib/plpdirent.h +++ b/lib/plpdirent.h @@ -157,4 +157,168 @@ private: string attrstr; string name; }; + +/** + * A class representing information about + * a Disk drive on the psion. An Object of this type + * is used by @ref rfsv::devinfo for returning the + * information of the probed drive. + * + * @author Fritz Elfert <felfert@to.com> + */ +class PlpDrive { + friend rfsv32; + friend rfsv16; + + public: + /** + * Default constructor. + */ + PlpDrive(); + + /** + * Copy constructor + */ + PlpDrive(const PlpDrive &other); + + /** + * Retrieve the media type of the drive. + * + * @returns The media type of the probed drive. + * <pre> + * Media types are encoded by a number + * in the range 0 .. 8 with the following + * meaning: + * + * 0 = Not present + * 1 = Unknown + * 2 = Floppy + * 3 = Disk + * 4 = CD-ROM + * 5 = RAM + * 6 = Flash Disk + * 7 = ROM + * 8 = Remote + * </pre> + */ + u_int32_t getMediaType(); + + /** + * Retrieve the media type of the drive. + * Just like the above function, but returns + * the media type as human readable string. + * + * @param ret The string is returned here. + */ + void getMediaType(string &ret); + + /** + * Retrieve the attributes of the drive. + * + * @returns The attributes of the probed drive. + * <pre> + * Drive attributes are encoded by a number + * in the range 0 .. 63. The bits have the + * the following meaning: + * + * bit 0 = local + * bit 1 = ROM + * bit 2 = redirected + * bit 3 = substituted + * bit 4 = internal + * bit 5 = removable + * </pre> + */ + u_int32_t getDriveAttribute(); + + /** + * Retrieve the attributes of the drive. + * Just like the above function, but returns + * the attributes as human readable string. + * + * @param ret The string is returned here. + */ + void getDriveAttribute(string &ret); + + /** + * Retrieve the attributes of the media. + * + * @returns The attributes of the probed media. + * <pre> + * Media attributes are encoded by a number + * in the range 0 .. 15. The bits have the + * following meaning: + * + * bit 0 = variable size + * bit 1 = dual density + * bit 2 = formattable + * bit 3 = write protected + * </pre> + */ + u_int32_t getMediaAttribute(); + + /** + * Retrieve the attributes of the media. + * Just like the above function, but returns + * the attributes as human readable string. + * + * @param ret The string is returned here. + */ + void getMediaAttribute(string &ret); + + /** + * Retrieve the UID of the drive. + * Each drive, except the ROM drive on a Psion has + * a unique ID which can be retrieved here. + * + * @returns The UID of the probed drive. + */ + u_int32_t getUID(); + + /** + * Retrieve the total capacity of the drive. + * + * @returns The capacity of the probed drive in bytes. + */ + u_int64_t getSize(); + + /** + * Retrieve the free capacity on the drive. + * + * @returns The free space on the probed drive in bytes. + */ + u_int64_t getSpace(); + + /** + * Retrieve the volume name of the drive. + * + * returns The volume name of the drive. + */ + string getName(); + + /** + * Retrieve the drive letter of the drive. + * + * returns The letter of the probed drive. + */ + char getDrivechar(); + + private: + void setMediaType(u_int32_t type); + void setDriveAttribute(u_int32_t attr); + void setMediaAttribute(u_int32_t attr); + void setUID(u_int32_t uid); + void setSize(u_int32_t sizeLo, u_int32_t sizeHi); + void setSpace(u_int32_t spaceLo, u_int32_t spaceHi); + void setName(char drive, const char * const volname); + + u_int32_t mediatype; + u_int32_t driveattr; + u_int32_t mediaattr; + u_int32_t uid; + u_int64_t size; + u_int64_t space; + char drivechar; + string name; +}; #endif diff --git a/lib/ppsocket.cc b/lib/ppsocket.cc index a482ae5..9b0a33d 100644 --- a/lib/ppsocket.cc +++ b/lib/ppsocket.cc @@ -38,6 +38,7 @@ #include "bufferstore.h" #include "ppsocket.h" +#include "iowatch.h" #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 @@ -49,6 +50,7 @@ ppsocket::ppsocket(const ppsocket & another) m_PeerAddr = another.m_PeerAddr; m_Bound = another.m_Bound; m_LastError = another.m_LastError; + myWatch = another.myWatch; } @@ -64,21 +66,32 @@ ppsocket::ppsocket() m_Bound = false; m_LastError = 0; + myWatch = 0L; } ppsocket::~ppsocket() { if (m_Socket != INVALID_SOCKET) { - shutdown(m_Socket, 3); + if (myWatch) + myWatch->remIO(m_Socket); + shutdown(m_Socket, SHUT_RDWR); ::close(m_Socket); } } +void ppsocket:: +setWatch(IOWatch *watch) { + if (watch) + myWatch = watch; +} + bool ppsocket:: reconnect() { if (m_Socket != INVALID_SOCKET) { - shutdown(m_Socket, 3); + if (myWatch) + myWatch->remIO(m_Socket); + shutdown(m_Socket, SHUT_RDWR); ::close(m_Socket); } m_Socket = INVALID_SOCKET; @@ -94,6 +107,8 @@ reconnect() m_LastError = errno; return (false); } + if (myWatch) + myWatch->addIO(m_Socket); return (true); } @@ -148,6 +163,8 @@ connect(const char * const Peer, int PeerPort, const char * const Host, int Host m_LastError = errno; return (false); } + if (myWatch) + myWatch->addIO(m_Socket); return (true); } @@ -167,6 +184,8 @@ listen(const char * const Host, int Port) //* Listen on the port * //********************** + if (myWatch) + myWatch->addIO(m_Socket); if (::listen(m_Socket, 5) != 0) { m_LastError = errno; return (false); @@ -215,11 +234,9 @@ accept(string *Peer) // Make sure the new socket hasn't inherited O_NONBLOCK // from the accept socket - int flags = fcntl( accepted->m_Socket, F_GETFL, 0 ); - if( flags >= 0 ) { - flags &= ~O_NONBLOCK; - fcntl( accepted->m_Socket, F_SETFL, flags); - } + int flags = fcntl(accepted->m_Socket, F_GETFL, 0); + flags &= ~O_NONBLOCK; + fcntl(accepted->m_Socket, F_SETFL, flags); accepted->m_HostAddr = m_HostAddr; accepted->m_Bound = true; @@ -232,18 +249,22 @@ accept(string *Peer) if (peer) *Peer = peer; } + if (accepted && myWatch) { + accepted->setWatch(myWatch); + myWatch->addIO(accepted->m_Socket); + } return accepted; } bool ppsocket:: -dataToGet() const +dataToGet(int sec, int usec) const { fd_set io; FD_ZERO(&io); FD_SET(m_Socket, &io); struct timeval t; - t.tv_usec = 0; - t.tv_sec = 0; + t.tv_usec = usec; + t.tv_sec = sec; return (select(m_Socket + 1, &io, NULL, NULL, &t) != 0) ? true : false; } @@ -258,16 +279,15 @@ getBufferStore(bufferStore & a, bool wait) long count = 0; unsigned char *buff; unsigned char *bp; - if (!wait && !dataToGet()) + if (!wait && !dataToGet(0, 0)) return 0; a.init(); - - if (recv(&l, sizeof(l), 0) != sizeof(l)) + if (recv(&l, sizeof(l), MSG_NOSIGNAL) != sizeof(l)) return -1; l = ntohl(l); bp = buff = new unsigned char[l]; while (l > 0) { - int j = recv(bp, l, 0); + int j = recv(bp, l, MSG_NOSIGNAL); if (j == SOCKET_ERROR || j == 0) { delete[]buff; return -1; @@ -290,11 +310,15 @@ sendBufferStore(const bufferStore & a) int retries = 0; int i; - i = send((char *) &hl, sizeof(hl), 0); - if (i != sizeof(hl)) - return false; + bufferStore b; + b.addDWord(hl); + b.addBuff(a); +// i = send((char *)&hl, sizeof(hl), MSG_NOSIGNAL); +// if (i != sizeof(hl)) +// return false; + l += 4; while (l > 0) { - i = send((const char *)a.getString(sent), l, 0); + i = send((const char *)b.getString(sent), l, MSG_NOSIGNAL); if (i == SOCKET_ERROR || i == 0) return (false); sent += i; @@ -332,7 +356,9 @@ send(const void * const buf, int len, int flags) bool ppsocket:: closeSocket(void) { - shutdown(m_Socket, 3); + if (myWatch) + myWatch->remIO(m_Socket); + shutdown(m_Socket, SHUT_RDWR); if (::close(m_Socket) != 0) { m_LastError = errno; return false; diff --git a/lib/ppsocket.h b/lib/ppsocket.h index 57cc788..b8f7ebe 100644 --- a/lib/ppsocket.h +++ b/lib/ppsocket.h @@ -8,6 +8,7 @@ #include <arpa/inet.h> class bufferStore; +class IOWatch; /** * A class for dealing with sockets. @@ -80,11 +81,14 @@ public: ppsocket *accept(string *Peer); /** - * Check for incoming data. + * Check and optionally wait for incoming data. + * + * @param sec Timeout in seconds + * @param usec Timeout in microseconds * * @returns true if data is available, false otherwise. */ - bool dataToGet() const; + bool dataToGet(int sec, int usec) const; /** * Receive data into a @ref bufferStore . @@ -169,11 +173,13 @@ public: bool getHost(string *Host, int *Port); /** - * Retrieves the socket number. + * Registers an @ref IOWatch for this socket. + * This IOWatch gets the socket added/removed + * automatically. * - * @returns the socket number. + * @param watch The IOWatch to register. */ - inline int socket(void) const { return(m_Socket); } + void setWatch(IOWatch *watch); private: /** @@ -193,6 +199,7 @@ public: int m_Port; bool m_Bound; int m_LastError; + IOWatch *myWatch; }; #endif @@ -10,6 +10,7 @@ typedef deque<class PlpDirent> PlpDir; class ppsocket; +class PlpDrive; const int RFSV_SENDLEN = 2000; @@ -19,8 +20,20 @@ const int RFSV_SENDLEN = 2000; */ typedef int (*cpCallback_t)(void *, u_int32_t); +class rfsv16; +class rfsv32; + +/** + * A helper class for storing + * intermediate internal information in rfsv16 and + * rfsv32 . + * @internal + */ class rfsvDirhandle { - public: + friend rfsv16; + friend rfsv32; + + private: u_int32_t h; bufferStore b; }; @@ -330,15 +343,12 @@ class rfsv { * * @param dev An integer, representing the drive to get details from. * (0 represents A:, 1 is B: and so on ...) - * @param free On return, the free space in bytes is returned here. - * @param total On return, the total capacity in bytes is returned here. - * @param attr On return, the attributes of the drive are returned here. - * @param uniqueid On return, the unique Id of the drive is returned here. - * @param name On return, the volume name returned here. + * @param drive A @ref PlpDrive object which is filled with the drive's + * information upon return. * * @returns A Psion error code (One of enum @ref #errs ). */ - virtual Enum<errs> devinfo(const u_int32_t dev, u_int32_t &free, u_int32_t &total, u_int32_t &attr, u_int32_t &uniqueid, string &name) = 0; + virtual Enum<errs> devinfo(const u_int32_t dev, PlpDrive &drive) = 0; /** * Reads from a file on the Psion. diff --git a/lib/rfsv16.cc b/lib/rfsv16.cc index 2b474cb..f98816c 100644 --- a/lib/rfsv16.cc +++ b/lib/rfsv16.cc @@ -413,8 +413,18 @@ devlist(u_int32_t &devbits) return res; } +static int sibo_dattr[] = { + 1, // Unknown + 2, // Floppy + 3, // Disk + 6, // Flash + 5, // RAM + 7, // ROM + 7, // write-protected == ROM ? +}; + Enum<rfsv::errs> rfsv16:: -devinfo(const u_int32_t devnum, u_int32_t &free, u_int32_t &size, u_int32_t &attr, u_int32_t &uniqueid, string &name) +devinfo(const u_int32_t devnum, PlpDrive &drive) { bufferStore a; Enum<rfsv::errs> res; @@ -448,16 +458,31 @@ devinfo(const u_int32_t devnum, u_int32_t &free, u_int32_t &size, u_int32_t &att // cerr << "devinfo STATUSDEVICE res is " << dec << (signed short int) res << endl; return res; } + + int attr = a.getWord(2); + attr = sibo_dattr[a.getWord(2) & 0xff]; + drive.setMediaType(attr); + attr = a.getWord(2); - // int changeable = a.getWord(4); - size = a.getDWord(6); - free = a.getDWord(10); - // const char *volume = a.getString(14); - // int battery = a.getWord(30); - // const char *devicename = a.getString(62); - uniqueid = 0; - name = ""; - name += (char)(devnum + 'A'); + int changeable = a.getWord(4) ? 32 : 0; + int internal = (attr & 0x2000) ? 16 : 0; + + drive.setDriveAttribute(changeable | internal); + + int variable = (attr & 0x4000) ? 1 : 0; + int dualdens = (attr & 0x1000) ? 2 : 0; + int formattable = (attr & 0x0800) ? 4 : 0; + int protect = ((attr & 0xff) == 6) ? 8 : 0; + + drive.setMediaAttribute(variable|dualdens|formattable|protect); + + drive.setUID(0); + drive.setSize(a.getDWord(6), 0); + drive.setSpace(a.getDWord(10), 0); + + drive.setName('A' + devnum, a.getString(14)); + + return res; } diff --git a/lib/rfsv16.h b/lib/rfsv16.h index a94aa5f..42661f8 100644 --- a/lib/rfsv16.h +++ b/lib/rfsv16.h @@ -3,15 +3,19 @@ #include "rfsv.h" +class rfsvfactory; + /** * This is the implementation of the @ref rfsv protocol for - * Psion series 3 (SIBO) variant. - * For a complete documentation, see @ref rfsv . + * Psion series 3 (SIBO) variant. You normally never create + * objects of this class directly. Thus the constructor is + * private. Use @ref rfsvfactory for creating an instance of + * @ref rfsv . For a complete documentation, see @ref rfsv . */ class rfsv16 : public rfsv { -public: - rfsv16(ppsocket *); + friend rfsvfactory; +public: Enum<rfsv::errs> fopen(const u_int32_t, const char * const, u_int32_t &); Enum<rfsv::errs> mktemp(u_int32_t &, string &); Enum<rfsv::errs> fcreatefile(const u_int32_t, const char * const, u_int32_t &); @@ -25,7 +29,7 @@ public: Enum<rfsv::errs> fsetattr(const char * const, const u_int32_t seta, const u_int32_t unseta); Enum<rfsv::errs> dircount(const char * const, u_int32_t &); Enum<rfsv::errs> devlist(u_int32_t &); - Enum<rfsv::errs> devinfo(const u_int32_t, u_int32_t &, u_int32_t &, u_int32_t &, u_int32_t &, string &); + Enum<rfsv::errs> devinfo(const u_int32_t, PlpDrive &); Enum<rfsv::errs> fread(const u_int32_t, unsigned char * const, const u_int32_t, u_int32_t &); Enum<rfsv::errs> fwrite(const u_int32_t, const unsigned char * const, const u_int32_t, u_int32_t &); Enum<rfsv::errs> copyFromPsion(const char * const, const char * const, void *, cpCallback_t); @@ -102,6 +106,11 @@ private: P_FAMASK = 0x0f3f /* All of the above */ }; + /** + * Private constructor. Shall be called by + * rfsvfactory only. + */ + rfsv16(ppsocket *); // Miscellaneous Enum<rfsv::errs> fopendir(const char * const, u_int32_t &); diff --git a/lib/rfsv32.cc b/lib/rfsv32.cc index 74a1959..0b6f120 100644 --- a/lib/rfsv32.cc +++ b/lib/rfsv32.cc @@ -358,7 +358,7 @@ devlist(u_int32_t &devbits) } Enum<rfsv::errs> rfsv32:: -devinfo(const u_int32_t dev, u_int32_t &free, u_int32_t &total, u_int32_t &attr, u_int32_t &uniqueid, string &name) +devinfo(const u_int32_t dev, PlpDrive &drive) { bufferStore a; Enum<rfsv::errs> res; @@ -368,13 +368,14 @@ devinfo(const u_int32_t dev, u_int32_t &free, u_int32_t &total, u_int32_t &attr, return E_PSI_FILE_DISC; res = getResponse(a); if (res == E_PSI_GEN_NONE) { - attr = a.getDWord(0); - uniqueid = a.getDWord(16); - total = a.getDWord(20); - free = a.getDWord(28); - // vnamelen = a.getDWord(36); + drive.setMediaType(a.getDWord(0)); + drive.setDriveAttribute(a.getDWord(8)); + drive.setMediaAttribute(a.getDWord(12)); + drive.setUID(a.getDWord(16)); + drive.setSize(a.getDWord(20), a.getDWord(24)); + drive.setSpace(a.getDWord(28), a.getDWord(32)); a.addByte(0); - name = a.getString(40); + drive.setName('A' + dev, a.getString(40)); } return res; } diff --git a/lib/rfsv32.h b/lib/rfsv32.h index abbc6ad..4afb95a 100644 --- a/lib/rfsv32.h +++ b/lib/rfsv32.h @@ -4,16 +4,19 @@ #include "rfsv.h" #include "plpdirent.h" +class rfsvfactory; + /** * This is the implementation of the @ref rfsv protocol for - * Psion series 5 (EPOC) variant. - * For a complete documentation, see @ref rfsv . + * Psion series 5 (EPOC) variant. You normally never create + * objects of this class directly. Thus the constructor is + * private. Use @ref rfsvfactory for creating an instance of + * @ref rfsv . For a complete documentation, see @ref rfsv . */ class rfsv32 : public rfsv { + friend rfsvfactory; public: - rfsv32(ppsocket *); - Enum<rfsv::errs> dir(const char * const, PlpDir &); Enum<rfsv::errs> dircount(const char * const, u_int32_t &); Enum<rfsv::errs> copyFromPsion(const char * const, const char * const, void *, cpCallback_t); @@ -39,7 +42,7 @@ public: Enum<rfsv::errs> fclose(const u_int32_t); Enum<rfsv::errs> devlist(u_int32_t &); - Enum<rfsv::errs> devinfo(const u_int32_t, u_int32_t &, u_int32_t &, u_int32_t &, u_int32_t &, string &); + Enum<rfsv::errs> devinfo(const u_int32_t, PlpDrive&); Enum<rfsv::errs> opendir(const u_int32_t, const char * const, rfsvDirhandle &); Enum<rfsv::errs> readdir(rfsvDirhandle &, PlpDirent &); Enum<rfsv::errs> closedir(rfsvDirhandle &); @@ -155,6 +158,12 @@ private: REPLACE = 0x32 }; + /** + * Private constructor. Shall be called by + * rfsvfactory only. + */ + rfsv32(ppsocket *); + Enum<rfsv::errs> err2psierr(int32_t); Enum<rfsv::errs> fopendir(const u_int32_t, const char *, u_int32_t &); u_int32_t attr2std(const u_int32_t); diff --git a/lib/rfsvfactory.cc b/lib/rfsvfactory.cc index 12bd623..3699903 100644 --- a/lib/rfsvfactory.cc +++ b/lib/rfsvfactory.cc @@ -35,10 +35,20 @@ #include "rfsvfactory.h" #include "bufferstore.h" #include "ppsocket.h" -#include "bufferarray.h" +#include "Enum.h" + +ENUM_DEFINITION(rfsvfactory::errs, rfsvfactory::FACERR_NONE) { + stringRep.add(rfsvfactory::FACERR_NONE, "no error"); + stringRep.add(rfsvfactory::FACERR_COULD_NOT_SEND, "could not send version request"); + stringRep.add(rfsvfactory::FACERR_AGAIN, "try again"); + stringRep.add(rfsvfactory::FACERR_NOPSION, "no psion connected"); + stringRep.add(rfsvfactory::FACERR_PROTVERSION, "wrong protocol version"); + stringRep.add(rfsvfactory::FACERR_NORESPONSE, "no response from ncpd"); +} rfsvfactory::rfsvfactory(ppsocket *_skt) : serNum(0) { + err = FACERR_NONE; skt = _skt; } @@ -50,15 +60,19 @@ rfsv * rfsvfactory::create(bool reconnect) // so we can instantiate the correct RFSV protocol handler for the // caller. We announce ourselves to the NCP daemon, and the relevant // RFSV module will also announce itself. + bufferStore a; - a.init(); + + err = FACERR_NONE; a.addStringT("NCP$INFO"); if (!skt->sendBufferStore(a)) { if (!reconnect) - cerr << "rfsvfactory::create couldn't send version request" << endl; else { + err = FACERR_COULD_NOT_SEND; + else { skt->closeSocket(); serNum = 0; skt->reconnect(); + err = FACERR_AGAIN; } return NULL; } @@ -73,16 +87,13 @@ rfsv * rfsvfactory::create(bool reconnect) skt->closeSocket(); serNum = 0; skt->reconnect(); + err = FACERR_NOPSION; return NULL; } // Invalid protocol version - cerr << "rfsvfactory::create received odd protocol version from -ncpd! (" << a << ")" << endl; - } else { - cerr << "rfsvfactory::create sent, response not 1" << endl; - } + err = FACERR_PROTVERSION; + } else + err = FACERR_NORESPONSE; - // No message returned. return NULL; } - diff --git a/lib/rfsvfactory.h b/lib/rfsvfactory.h index 99136e3..8af4575 100644 --- a/lib/rfsvfactory.h +++ b/lib/rfsvfactory.h @@ -10,8 +10,21 @@ class ppsocket; * @ref rfsv protocol variant depending on the connected Psion. */ class rfsvfactory { + public: /** + * The known errors which can happen during @ref create . + */ + enum errs { + FACERR_NONE = 0, + FACERR_COULD_NOT_SEND = 1, + FACERR_AGAIN = 2, + FACERR_NOPSION = 3, + FACERR_PROTVERSION = 4, + FACERR_NORESPONSE = 5, + }; + + /** * Constructs a rfsvfactory. * * @param skt The socket to be used for connecting @@ -30,6 +43,14 @@ class rfsvfactory { */ virtual rfsv * create(bool); + /** + * Retrieve an error code. + * + * @returns The error code, in case @ref create has + * failed, 0 otherwise. + */ + virtual Enum<errs> getError() { return err; } + private: /** * The socket to be used for connecting to the @@ -37,6 +58,7 @@ class rfsvfactory { */ ppsocket *skt; int serNum; + Enum<errs> err; }; #endif diff --git a/lib/rpcs16.h b/lib/rpcs16.h index 7085939..cc4d601 100644 --- a/lib/rpcs16.h +++ b/lib/rpcs16.h @@ -5,19 +5,25 @@ class ppsocket; class bufferStore; +class rpcsfactory; /** * This is the implementation of the @ref rpcs protocol for - * Psion series 3 (SIBO) variant. - * For a complete documentation, see @ref rpcs . + * Psion series 3 (SIBO) variant. You normally never create + * objects of this class directly. Thus the constructor is + * private. Use @ref rpcsfactory for creating an instance of + * @ref rpcs . For a complete documentation, see @ref rpcs . */ class rpcs16 : public rpcs { + friend rpcsfactory; + public: - rpcs16(ppsocket *); ~rpcs16(); Enum<rfsv::errs> queryDrive(const char, bufferArray &); Enum<rfsv::errs> getCmdLine(const char *, bufferStore &); + private: + rpcs16(ppsocket *); }; #endif diff --git a/lib/rpcs32.h b/lib/rpcs32.h index 0cab1b2..5230247 100644 --- a/lib/rpcs32.h +++ b/lib/rpcs32.h @@ -4,40 +4,45 @@ #include "rpcs.h" class ppsocket; +class rpcsfactory; /** * This is the implementation of the @ref rpcs protocol for - * Psion series 5 (EPOC) variant. - * For a complete documentation, see @ref rpcs . + * Psion series 5 (EPOC) variant. You normally never create + * objects of this class directly. Thus the constructor is + * private. Use @ref rpcsfactory for creating an instance of + * @ref rpcs . For a complete documentation, see @ref rpcs . */ class rpcs32 : public rpcs { - public: - rpcs32(ppsocket *); - ~rpcs32(); + friend rpcsfactory; - Enum<rfsv::errs> queryDrive(const char, bufferArray &); - Enum<rfsv::errs> getCmdLine(const char *, bufferStore &); - Enum<rfsv::errs> getMachineInfo(machineInfo &); - Enum<rfsv::errs> configOpen(void); - Enum<rfsv::errs> configRead(void); + public: + ~rpcs32(); + + Enum<rfsv::errs> queryDrive(const char, bufferArray &); + Enum<rfsv::errs> getCmdLine(const char *, bufferStore &); + Enum<rfsv::errs> getMachineInfo(machineInfo &); + Enum<rfsv::errs> configOpen(void); + Enum<rfsv::errs> configRead(void); #if 0 - Enum<rfsv::errs> closeHandle(int); + Enum<rfsv::errs> closeHandle(int); #endif - Enum<rfsv::errs> regOpenIter(void); + Enum<rfsv::errs> regOpenIter(void); #if 0 - Enum<rfsv::errs> regReadIter(void); - Enum<rfsv::errs> regWrite(void); - Enum<rfsv::errs> regRead(void); - Enum<rfsv::errs> regDelete(void); - Enum<rfsv::errs> setTime(void); - Enum<rfsv::errs> configOpen(void); - Enum<rfsv::errs> configRead(void); - Enum<rfsv::errs> configWrite(void); - Enum<rfsv::errs> queryOpen(void); - Enum<rfsv::errs> queryRead(void); - Enum<rfsv::errs> quitServer(void); + Enum<rfsv::errs> regReadIter(void); + Enum<rfsv::errs> regWrite(void); + Enum<rfsv::errs> regRead(void); + Enum<rfsv::errs> regDelete(void); + Enum<rfsv::errs> setTime(void); + Enum<rfsv::errs> configOpen(void); + Enum<rfsv::errs> configRead(void); + Enum<rfsv::errs> configWrite(void); + Enum<rfsv::errs> queryOpen(void); + Enum<rfsv::errs> queryRead(void); + Enum<rfsv::errs> quitServer(void); #endif - + private: + rpcs32(ppsocket *); }; #endif diff --git a/lib/rpcsfactory.cc b/lib/rpcsfactory.cc index 091f12a..bd3b77d 100644 --- a/lib/rpcsfactory.cc +++ b/lib/rpcsfactory.cc @@ -36,8 +36,20 @@ #include "bufferstore.h" #include "ppsocket.h" +#include "Enum.h" + +ENUM_DEFINITION(rpcsfactory::errs, rpcsfactory::FACERR_NONE) { + stringRep.add(rpcsfactory::FACERR_NONE, "no error"); + stringRep.add(rpcsfactory::FACERR_COULD_NOT_SEND, "could not send version request"); + stringRep.add(rpcsfactory::FACERR_AGAIN, "try again"); + stringRep.add(rpcsfactory::FACERR_NOPSION, "no psion connected"); + stringRep.add(rpcsfactory::FACERR_PROTVERSION, "wrong protocol version"); + stringRep.add(rpcsfactory::FACERR_NORESPONSE, "no response from ncpd"); +} + rpcsfactory::rpcsfactory(ppsocket *_skt) { + err = FACERR_NONE; skt = _skt; } @@ -49,15 +61,18 @@ rpcs * rpcsfactory::create(bool reconnect) // so we can instantiate the correct rpcs protocol handler for the // caller. We announce ourselves to the NCP daemon, and the relevant // rpcs module will also announce itself. + bufferStore a; - a.init(); + + err = FACERR_NONE; a.addStringT("NCP$INFO"); if (!skt->sendBufferStore(a)) { if (!reconnect) - cerr << "rpcsfactory::create couldn't send version request" << endl; + err = FACERR_COULD_NOT_SEND; else { skt->closeSocket(); skt->reconnect(); + err = FACERR_AGAIN; } return NULL; } @@ -71,13 +86,13 @@ rpcs * rpcsfactory::create(bool reconnect) if ((a.getLen() > 8) && !strncmp(a.getString(), "No Psion", 8)) { skt->closeSocket(); skt->reconnect(); + err = FACERR_NOPSION; return NULL; } // Invalid protocol version - cerr << "rpcsfactory::create received odd protocol version from ncpd! (" << a << ")" << endl; - } else { - cerr << "rpcsfactory::create sent, response not 1" << endl; - } + err = FACERR_PROTVERSION; + } else + err = FACERR_NORESPONSE; // No message returned. return NULL; diff --git a/lib/rpcsfactory.h b/lib/rpcsfactory.h index d57eb29..cc36f0d 100644 --- a/lib/rpcsfactory.h +++ b/lib/rpcsfactory.h @@ -11,6 +11,19 @@ class ppsocket; */ class rpcsfactory { public: + + /** + * The known errors which can happen during @ref create . + */ + enum errs { + FACERR_NONE = 0, + FACERR_COULD_NOT_SEND = 1, + FACERR_AGAIN = 2, + FACERR_NOPSION = 3, + FACERR_PROTVERSION = 4, + FACERR_NORESPONSE = 5, + }; + /** * Constructs a rpcsfactory. * @@ -30,12 +43,21 @@ class rpcsfactory { */ virtual rpcs * create(bool reconnect); + /** + * Retrieve an error code. + * + * @returns The error code, in case @ref create has + * failed, 0 otherwise. + */ + virtual Enum<errs> getError() { return err; } + private: /** * The socket to be used for connecting to the * ncpd daemon. */ ppsocket *skt; + Enum<errs> err; }; #endif diff --git a/ncpd/main.cc b/ncpd/main.cc index 76d0bb2..d8a28ed 100644 --- a/ncpd/main.cc +++ b/ncpd/main.cc @@ -63,7 +63,7 @@ int_handler(int) }; void -checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp * a, IOWatch & iow) +checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp * a, IOWatch &iow) { string peer; ppsocket *next = skt.accept(&peer); @@ -73,11 +73,17 @@ checkForNewSocketConnection(ppsocket & skt, int &numScp, socketChan ** scp, ncp cout << "New socket connection from " << peer << endl; if ((numScp == 7) || (!a->gotLinkChannel())) { bufferStore a; + + // Give the client time to send it's version request. + next->dataToGet(1,0); + next->getBufferStore(a, false); + + a.init(); a.addStringT("No Psion Connected\n"); next->sendBufferStore(a); next->closeSocket(); } else - scp[numScp++] = new socketChan(next, a, iow); + scp[numScp++] = new socketChan(next, a); } } @@ -126,7 +132,6 @@ main(int argc, char **argv) sockNum = ntohs(se->s_port); // Command line parameter processing - signal(SIGPIPE, SIG_IGN); for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-p") && i + 1 < argc) { sockNum = atoi(argv[++i]); @@ -187,6 +192,7 @@ main(int argc, char **argv) case 0: signal(SIGTERM, term_handler); signal(SIGINT, int_handler); + skt.setWatch(&iow); if (!skt.listen("127.0.0.1", sockNum)) cerr << "listen on port " << sockNum << ": " << strerror(errno) << endl; else { @@ -209,7 +215,6 @@ main(int argc, char **argv) a->setVerbose(nverbose); a->setLinkVerbose(lverbose); a->setPktVerbose(pverbose); - iow.addIO(skt.socket()); while (active) { // sockets pollSocketConnections(numScp, scp); diff --git a/ncpd/socketchan.cc b/ncpd/socketchan.cc index 1e3fd08..06b3da2 100644 --- a/ncpd/socketchan.cc +++ b/ncpd/socketchan.cc @@ -33,22 +33,18 @@ #include "socketchan.h" #include "ncp.h" #include "ppsocket.h" -#include "iowatch.h" -socketChan:: socketChan(ppsocket * _skt, ncp * _ncpController, IOWatch & _iow): -channel(_ncpController), -iow(_iow) +socketChan:: socketChan(ppsocket * _skt, ncp * _ncpController): + channel(_ncpController) { skt = _skt; connectName = 0; connectTry = 0; - iow.addIO(skt->socket()); connected = false; } socketChan::~socketChan() { - iow.remIO(skt->socket()); skt->closeSocket(); delete skt; if (connectName) diff --git a/ncpd/socketchan.h b/ncpd/socketchan.h index 15645dd..7dde472 100644 --- a/ncpd/socketchan.h +++ b/ncpd/socketchan.h @@ -30,11 +30,10 @@ #endif #include "channel.h" class ppsocket; -class IOWatch; class socketChan : public channel { public: - socketChan(ppsocket* comms, ncp* ncpController, IOWatch &iow); + socketChan(ppsocket* comms, ncp* ncpController); virtual ~socketChan(); void ncpDataCallback(bufferStore& a); @@ -51,7 +50,6 @@ private: enum protocolVersionType { PV_SERIES_5 = 6, PV_SERIES_3 = 3 }; bool ncpCommand(bufferStore &a); ppsocket* skt; - IOWatch &iow; char* connectName; bool connected; int connectTry; diff --git a/plpbackup/plpbackup.cc b/plpbackup/plpbackup.cc index 48e3202..adf8742 100644 --- a/plpbackup/plpbackup.cc +++ b/plpbackup/plpbackup.cc @@ -31,7 +31,6 @@ #include <stdlib.h> #include <iomanip.h> #include <unistd.h> -#include <signal.h> #include <sys/time.h> #include <sys/stat.h> #include <errno.h> @@ -292,11 +291,6 @@ main(int argc, char **argv) int op; char dstPath[1024]; struct passwd *pw; - sigset_t sigset; - - sigemptyset(&sigset); - sigaddset(&sigset, SIGPIPE); - sigprocmask(SIG_BLOCK, &sigset, 0L); struct servent *se = getservbyname("psion", "tcp"); endservent(); @@ -417,13 +411,12 @@ main(int argc, char **argv) } else { char drive[3]; u_int32_t devbits; - u_int32_t vtotal, vfree, vattr, vuniqueid; if (a->devlist(devbits) == rfsv::E_PSI_GEN_NONE) { for (i = 0; i < 26; i++) { - string n; - if ((devbits & 1) && a->devinfo(i, vfree, vtotal, vattr, vuniqueid, n) == rfsv::E_PSI_GEN_NONE) { - if (vattr != 7) { + PlpDrive psidr; + if ((devbits & 1) && a->devinfo(i, psidr) == rfsv::E_PSI_GEN_NONE) { + if (psidr.getMediaType() != 7) { sprintf(drive, "%c:\0", 'A' + i); if (verbose > 0) cout << "Scanning Drive " << drive << " ..." << endl; diff --git a/plpftp/ftp.cc b/plpftp/ftp.cc index aad6187..efe4f82 100644 --- a/plpftp/ftp.cc +++ b/plpftp/ftp.cc @@ -242,15 +242,14 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) if (!strcmp(DDRIVE, "AUTO")) { u_int32_t devbits; - u_int32_t vtotal, vfree, vattr, vuniqueid; int i; strcpy(defDrive, "::"); if (a.devlist(devbits) == rfsv::E_PSI_GEN_NONE) { for (i = 0; i < 26; i++) { - string n; - if ((devbits & 1) && a.devinfo(i, vfree, vtotal, vattr, vuniqueid, n) == rfsv::E_PSI_GEN_NONE) { + PlpDrive drive; + if ((devbits & 1) && a.devinfo(i, drive) == rfsv::E_PSI_GEN_NONE) { defDrive[0] = 'A' + i; break; } @@ -417,17 +416,16 @@ session(rfsv & a, rpcs & r, int xargc, char **xargv) if ((res = a.devlist(devbits)) == rfsv::E_PSI_GEN_NONE) { cout << "Drive Type Volname Total Free UniqueID" << endl; for (int i = 0; i < 26; i++) { - string vname; - u_int32_t vtotal, vfree, vattr, vuniqueid; + PlpDrive drive; if ((devbits & 1) != 0) { - if (a.devinfo(i, vfree, vtotal, vattr, vuniqueid, vname) == rfsv::E_PSI_GEN_NONE) + if (a.devinfo(i, drive) == rfsv::E_PSI_GEN_NONE) cout << (char) ('A' + i) << " " << - hex << setw(4) << setfill('0') << vattr << " " << + hex << setw(4) << setfill('0') << drive.getMediaType() << " " << setw(12) << setfill(' ') << setiosflags(ios::left) << - vname << resetiosflags(ios::left) << dec << setw(9) << - vtotal << setw(9) << vfree << " " << setw(8) << setfill('0') << hex << - vuniqueid << endl; + drive.getName() << resetiosflags(ios::left) << dec << setw(9) << + drive.getSize() << setw(9) << drive.getSpace() << " " << setw(8) << setfill('0') << hex << + drive.getUID() << endl; } devbits >>= 1; } diff --git a/plpftp/main.cc b/plpftp/main.cc index 1755f38..ca3bcaa 100644 --- a/plpftp/main.cc +++ b/plpftp/main.cc @@ -30,7 +30,6 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> -#include <signal.h> #include "ppsocket.h" #include "rfsv.h" @@ -71,11 +70,6 @@ main(int argc, char **argv) ftp f; int status = 0; int sockNum = DPORT; - sigset_t sigset; - - sigemptyset(&sigset); - sigaddset(&sigset, SIGPIPE); - sigprocmask(SIG_BLOCK, &sigset, 0L); struct servent *se = getservbyname("psion", "tcp"); endservent(); diff --git a/plpnfsd/main.cc b/plpnfsd/main.cc index 81e7176..e7e3640 100644 --- a/plpnfsd/main.cc +++ b/plpnfsd/main.cc @@ -405,13 +405,12 @@ long rfsv_getattr(const char *name, long *attr, long *size, long *time) { } long rfsv_statdev(char letter) { - u_int32_t vfree, vtotal, vattr, vuniqueid; + PlpDrive drive; u_int32_t devnum = letter - 'A'; - string n; if (!a) return -1; - return (a->devinfo(devnum, vfree, vtotal, vattr, vuniqueid, n) != rfsv::E_PSI_GEN_NONE); + return (a->devinfo(devnum, drive) != rfsv::E_PSI_GEN_NONE); } long rfsv_rename(const char *oldname, const char *newname) { @@ -431,19 +430,19 @@ long rfsv_drivelist(int *cnt, device **dlist) { ret = a->devlist(devbits); if (ret == 0) for (i = 0; i<26; i++) { - string name; - u_int32_t vtotal, vfree, vattr, vuniqueid; + PlpDrive drive; if ((devbits & 1) && - ((a->devinfo(i, vfree, vtotal, vattr, vuniqueid, name) == rfsv::E_PSI_GEN_NONE))) { + ((a->devinfo(i, drive) == rfsv::E_PSI_GEN_NONE))) { + device *next = *dlist; *dlist = (device *)malloc(sizeof(device)); (*dlist)->next = next; - (*dlist)->name = strdup(name.c_str()); - (*dlist)->total = vtotal; - (*dlist)->free = vfree; + (*dlist)->name = strdup(drive.getName().c_str()); + (*dlist)->total = drive.getSize(); + (*dlist)->free = drive.getSpace(); (*dlist)->letter = 'A' + i; - (*dlist)->attrib = vattr; + (*dlist)->attrib = drive.getMediaType(); (*cnt)++; } devbits >>= 1; @@ -489,7 +488,6 @@ int main(int argc, char**argv) { usage(); } - signal(SIGPIPE, SIG_IGN); skt = new ppsocket(); if (!skt->connect(NULL, sockNum)) { cerr << "plpnfsd: could not connect to ncpd" << endl; diff --git a/plpnfsd/mp_mount.c b/plpnfsd/mp_mount.c index 6f9d203..39c3493 100644 --- a/plpnfsd/mp_mount.c +++ b/plpnfsd/mp_mount.c @@ -576,7 +576,6 @@ mount_and_run(char *dir, void (*proc)(), nfs_fh *root_fh) signal(SIGUSR1, usr1_handler); signal(SIGHUP, hup_handler); signal(SIGTERM, term_handler); - signal(SIGPIPE, SIG_IGN); for (;;) { fd_set readfd; |