aboutsummaryrefslogtreecommitdiffstats
path: root/plpfuse
diff options
context:
space:
mode:
authorReuben Thomas <rrt@sc3d.org>2007-12-13 23:40:55 +0000
committerReuben Thomas <rrt@sc3d.org>2007-12-13 23:40:55 +0000
commit270a30c1a350d791053937c72e6ce6cc63a64088 (patch)
tree7226a44551e3f093b43b00eea212ca2b758e46cd /plpfuse
parent2aea4578fe73119387d81f9c67e8221b5ad48eea (diff)
downloadplptools-270a30c1a350d791053937c72e6ce6cc63a64088.tar.gz
plptools-270a30c1a350d791053937c72e6ce6cc63a64088.tar.bz2
plptools-270a30c1a350d791053937c72e6ce6cc63a64088.zip
Replace plpnfsd with plpfuse.
Other minor simplifications to the build system.
Diffstat (limited to 'plpfuse')
-rw-r--r--plpfuse/.cvsignore5
-rw-r--r--plpfuse/Makefile.am9
-rw-r--r--plpfuse/fuse.c528
-rw-r--r--plpfuse/main.cc380
-rw-r--r--plpfuse/plpfuse.h52
-rw-r--r--plpfuse/rfsv_api.h76
6 files changed, 1050 insertions, 0 deletions
diff --git a/plpfuse/.cvsignore b/plpfuse/.cvsignore
new file mode 100644
index 0000000..6ccdb58
--- /dev/null
+++ b/plpfuse/.cvsignore
@@ -0,0 +1,5 @@
+Makefile.in
+Makefile
+.libs
+.deps
+plpfuse
diff --git a/plpfuse/Makefile.am b/plpfuse/Makefile.am
new file mode 100644
index 0000000..467baaf
--- /dev/null
+++ b/plpfuse/Makefile.am
@@ -0,0 +1,9 @@
+# $Id$
+#
+INCLUDES=-I$(top_srcdir)/lib
+
+sbin_PROGRAMS = plpfuse
+plpfuse_LDADD = $(LIB_PLP) $(INTLLIBS) -lfuse
+plpfuse_SOURCES = main.cc fuse.c
+
+EXTRA_DIST = rfsv_api.h
diff --git a/plpfuse/fuse.c b/plpfuse/fuse.c
new file mode 100644
index 0000000..92720e2
--- /dev/null
+++ b/plpfuse/fuse.c
@@ -0,0 +1,528 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2007 Reuben Thomas <rrt@sc3d.org>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
+// FIXME: Map errors sensibly from EPOC to UNIX
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include <fuse.h>
+#include "rfsv_api.h"
+
+#include "plpfuse.h"
+
+#define NO_PSION ENOMEDIUM
+
+int debug;
+
+int
+debuglog(char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+
+ //if (!debug)
+ // return 0;
+ va_start(ap, fmt);
+ vasprintf(&buf, fmt, ap);
+ syslog(LOG_DEBUG, "%s", buf);
+ free(buf);
+ va_end(ap);
+ return 0;
+}
+
+static void
+attr2pattr(long oattr, long nattr, long *psisattr, long *psidattr)
+{
+ /*
+ * Following flags have to be set in order to let backups
+ * work properly
+ */
+ *psisattr = *psidattr = 0;
+ if ((oattr & 0400) != (nattr & 0400)) {
+ if (nattr & 0400) /* readable */
+ *psisattr |= PSI_A_READ;
+ else
+ *psidattr |= PSI_A_READ;
+ }
+ if ((oattr & 0200) != (nattr & 0200)) {
+ if (nattr & 0200) /* Not writable -> readonly */
+ *psidattr |= PSI_A_RDONLY;
+ else
+ *psisattr |= PSI_A_RDONLY;
+ }
+ if ((oattr & 0020) != (nattr & 0020)) {
+ if (nattr & 0020) /* group-write -> archive */
+ *psisattr |= PSI_A_ARCHIVE;
+ else
+ *psidattr |= PSI_A_ARCHIVE;
+ }
+ if ((oattr & 0004) != (nattr & 0004)) {
+ if (nattr & 0004) /* Not world-read -> hidden */
+ *psidattr |= PSI_A_HIDDEN;
+ else
+ *psisattr |= PSI_A_HIDDEN;
+ }
+ if ((oattr & 0002) != (nattr & 0002)) {
+ if (nattr & 0002) /* world-write -> system */
+ *psisattr |= PSI_A_SYSTEM;
+ else
+ *psidattr |= PSI_A_SYSTEM;
+ }
+}
+
+static void
+pattr2attr(long psiattr, long size, long ftime, struct stat *st)
+{
+ struct fuse_context *ct = fuse_get_context();
+
+ memset(st, 0, sizeof(*st));
+
+ st->st_uid = ct->uid;
+ st->st_gid = ct->gid;
+
+ if (psiattr & PSI_A_DIR) {
+ st->st_mode = 0700 | S_IFDIR;
+ st->st_blocks = 1;
+ st->st_size = BLOCKSIZE;
+ st->st_nlink = 2; /* Call dircount for more accurate count */
+ } else {
+ st->st_blocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
+ st->st_size = size;
+ st->st_nlink = 1;
+ st->st_mode = S_IFREG;
+
+ /*
+ * Following flags have to be set in order to let backups
+ * work properly
+ */
+ if (psiattr & PSI_A_READ)
+ st->st_mode |= 0400; /* File readable (?) */
+ if (!(psiattr & PSI_A_RDONLY))
+ st->st_mode |= 0200; /* File writeable */
+ /* st->st_mode |= 0100; File executable */
+ if (!(psiattr & PSI_A_HIDDEN))
+ st->st_mode |= 0004; /* Not Hidden <-> world read */
+ if (psiattr & PSI_A_SYSTEM)
+ st->st_mode |= 0002; /* System <-> world write */
+ if (psiattr & PSI_A_VOLUME)
+ st->st_mode |= 0001; /* Volume <-> world exec */
+ if (psiattr & PSI_A_ARCHIVE)
+ st->st_mode |= 0020; /* Modified <-> group write */
+ /* st->st_mode |= 0040; Byte <-> group read */
+ /* st->st_mode |= 0010; Text <-> group exec */
+ }
+
+ st->st_mtime = st->st_ctime = st->st_atime = ftime;
+}
+
+static device *devices;
+
+static int
+query_devices()
+{
+ device *dp, *np;
+ int link_count = 2; /* set the root link count */
+
+ for (dp = devices; dp; dp = np) {
+ np = dp->next;
+ free(dp->name);
+ free(dp);
+ }
+ devices = NULL;
+ if (rfsv_drivelist(&link_count, &devices))
+ return 1;
+ return 0;
+}
+
+char *
+dirname(const char *dir)
+{
+ static char *namebuf = NULL;
+ if (namebuf)
+ free(namebuf);
+ asprintf(&namebuf, "%s\\", dir);
+ return namebuf;
+}
+
+const char *
+filname(const char *dir)
+{
+ char *p;
+ if ((p = (char *) rindex(dir, '\\')))
+ return p + 1;
+ else
+ return dir;
+}
+
+static int
+dircount(const char *path, long *count)
+{
+ dentry *e = NULL;
+ long ret = 0;
+
+ *count = 0;
+ debuglog("dircount: %s", path);
+ debuglog("RFSV dir %s", path);
+ if ((ret = rfsv_dir(dirname(path), &e)))
+ return ret;
+ while (e) {
+ struct stat st;
+ dentry *o = e;
+ pattr2attr(e->attr, e->size, e->time, &st);
+ free(e->name);
+ e = e->next;
+ free(o);
+ if (st.st_nlink > 1)
+ (*count)++;
+ }
+
+ debuglog("count %d", *count);
+ return ret;
+}
+
+static int getlinks(const char *path, struct stat *st)
+{
+ long dcount;
+
+ if (dircount(path, &dcount))
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+ st->st_nlink = dcount + 2;
+ return 0;
+}
+
+static int plp_getattr(const char *path, struct stat *st)
+{
+ debuglog("plp_getattr `%s'", ++path);
+
+ if (strcmp(path, "") == 0) {
+ pattr2attr(PSI_A_DIR, 0, 0, st);
+ if (!query_devices()) {
+ device *dp;
+
+ for (dp = devices; dp; dp = dp->next)
+ st->st_nlink++;
+ debuglog("root has %d links", st->st_nlink);
+ } else
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+ } else {
+ long pattr, psize, ptime;
+
+ if (strlen(path) == 2 && path[1] == ':') {
+ debuglog("getattr: device");
+ if (!query_devices()) {
+ device *dp;
+
+ for (dp = devices; dp; dp = dp->next) {
+ debuglog("cmp '%c', '%c'", dp->letter,
+ path[0]);
+ if (dp->letter == path[0])
+ break;
+ }
+ debuglog("device: %s", dp ? "exists" : "does not exist");
+ pattr2attr(PSI_A_DIR, 0, 0, st);
+ return getlinks(path, st);
+ } else
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+ }
+
+ debuglog("getattr: fileordir");
+ if (rfsv_getattr(path, &pattr, &psize, &ptime))
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+ else {
+ pattr2attr(pattr, psize, ptime, st);
+ debuglog(" attrs Psion: %x %d %d, UNIX modes: %o", pattr, psize, ptime, st->st_mode);
+ if (st->st_nlink > 1)
+ return getlinks(path, st);
+ }
+ }
+
+ debuglog("getattr: return OK");
+ return 0;
+}
+
+static int plp_access(const char *path, int mask)
+{
+ debuglog("plp_access `%s'", ++path);
+ return 0;
+}
+
+static int plp_readlink(const char *path, char *buf, size_t size)
+{
+ debuglog("plp_readlink `%s'", ++path);
+ return -EINVAL;
+}
+
+
+static int plp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ device *dp;
+ int ret;
+ dentry *e = NULL;
+
+ debuglog("plp_readdir `%s'", ++path);
+
+ (void)offset;
+ (void)fi;
+
+ if (strcmp(path, "") == 0) {
+ debuglog("readdir root");
+ if (query_devices() == 0) {
+ for (dp = devices; dp; dp = dp->next) {
+ dentry *o;
+ struct stat st;
+ unsigned char name[3];
+
+ name[0] = dp->letter;
+ name[1] = ':';
+ name[2] = '\0';
+ pattr2attr(dp->attrib, 1, 0, &st);
+ if (filler(buf, name, &st, 0))
+ break;
+ }
+ }
+ } else {
+ debuglog("RFSV dir `%s'", dirname(path));
+ if (rfsv_dir(dirname(path), &e))
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+
+ debuglog("scanning contents");
+ while (e) {
+ dentry *o;
+ struct stat st;
+ const char *name = filname(e->name);
+
+ pattr2attr(e->attr, e->size, e->time, &st);
+ debuglog(" %s %o %d %d", name, st.st_mode, st.st_size, st.st_mtime);
+ if (filler(buf, name, &st, 0))
+ break;
+ free(e->name);
+ o = e;
+ e = e->next;
+ free(o);
+ }
+ }
+
+ debuglog("readdir OK");
+ return 0;
+}
+
+static int plp_mknod(const char *path, mode_t mode, dev_t dev)
+{
+ u_int32_t phandle;
+
+ debuglog("plp_mknod `%s' %o", ++path, mode);
+
+ if (S_ISREG(mode) && dev == 0) {
+ if (rfsv_fcreate(0x200, path, &phandle))
+ return rfsv_isalive() ? -ENAMETOOLONG : -NO_PSION;
+ rfsv_fclose(phandle);
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int plp_mkdir(const char *path, mode_t mode)
+{
+ debuglog("plp_mkdir `%s' %o", ++path, mode);
+
+ if (rfsv_mkdir(path))
+ return rfsv_isalive() ? -ENAMETOOLONG : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_unlink(const char *path)
+{
+ debuglog("plp_unlink `%s'", ++path);
+
+ if (rfsv_remove(path))
+ return rfsv_isalive() ? -EACCES : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_rmdir(const char *path)
+{
+ debuglog("plp_rmdir `%s'", ++path);
+
+ if (rfsv_rmdir(path))
+ return rfsv_isalive() ? -EACCES : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_symlink(const char *from, const char *to)
+{
+ debuglog("plp_symlink `%s' -> `'%s'", ++from, ++to);
+ return -EPERM;
+}
+
+static int plp_rename(const char *from, const char *to)
+{
+ debuglog("plp_rename `%s' -> `%s'", ++from, ++to);
+
+ rfsv_remove(to);
+ if (rfsv_rename(from, to))
+ return rfsv_isalive() ? -EACCES : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_link(const char *from, const char *to)
+{
+ debuglog("plp_link `%s' -> `%s'", ++from, ++to);
+ return -EPERM;
+}
+
+static int plp_chmod(const char *path, mode_t mode)
+{
+ long psisattr, psidattr, pattr, psize, ptime;
+ struct stat st;
+
+ debuglog("plp_chmod `%s'", ++path);
+
+ if (rfsv_getattr(path, &pattr, &psize, &ptime))
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+ pattr2attr(pattr, psize, ptime, &st);
+ attr2pattr(st.st_mode, mode, &psisattr, &psidattr);
+ debuglog(" UNIX old, new: %o, %o; Psion set, clear: %x, %x", st.st_mode, mode, psisattr, psidattr);
+ if (rfsv_setattr(path, psisattr, psidattr))
+ return rfsv_isalive() ? -EACCES : -NO_PSION;
+
+ debuglog("chmod succeeded");
+ return 0;
+}
+
+static int plp_chown(const char *path, uid_t uid, gid_t gid)
+{
+ debuglog("plp_chown `%s'", ++path);
+ return -EPERM;
+}
+
+static int plp_truncate(const char *path, off_t size)
+{
+ debuglog("plp_truncate `%s'", ++path);
+
+ if (rfsv_setsize(path, 0))
+ return rfsv_isalive() ? -EPERM : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_utimens(const char *path, const struct timespec ts[2])
+{
+ struct timeval tv[2];
+
+ debuglog("plp_utimens `%s'", ++path);
+
+ if (rfsv_setmtime(path, ts[1].tv_sec))
+ return rfsv_isalive() ? -EPERM : -NO_PSION;
+
+ return 0;
+}
+
+static int plp_open(const char *path, struct fuse_file_info *fi)
+{
+ debuglog("plp_open `%s'", ++path);
+ (void)fi;
+ return 0;
+}
+
+static int plp_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ long read;
+
+ (void)fi;
+ debuglog("plp_read `%s' offset %lld size %ld", ++path, offset, size);
+
+ if ((read = rfsv_read(buf, (long)offset, size, path)) < 0)
+ return rfsv_isalive() ? -ENOENT : -NO_PSION;
+
+ debuglog("read %ld bytes", read);
+ return read;
+}
+
+static int plp_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ long written;
+
+ (void)fi;
+ debuglog("plp_write `%s' offset %lld size %ld", ++path, offset, size);
+ if ((written = rfsv_write(buf, offset, size, path)) < 0)
+ return rfsv_isalive() ? -ENOSPC : -NO_PSION;
+
+ debuglog("wrote %ld bytes", written);
+ return written;
+}
+
+static int plp_statfs(const char *path, struct statvfs *stbuf)
+{
+ device *dp;
+
+ debuglog("plp_statfs");
+
+ stbuf->f_bsize = BLOCKSIZE;
+ stbuf->f_frsize = BLOCKSIZE;
+ if (query_devices() == 0) {
+ for (dp = devices; dp; dp = dp->next) {
+ stbuf->f_blocks += (dp->total + BLOCKSIZE - 1) / BLOCKSIZE;
+ stbuf->f_bfree += (dp->free + BLOCKSIZE - 1) / BLOCKSIZE;
+ }
+ }
+ stbuf->f_bavail = stbuf->f_bfree;
+
+ /* Don't have numbers for these */
+ stbuf->f_files = 0;
+ stbuf->f_ffree = stbuf->f_favail = 0;
+
+ stbuf->f_fsid = FID;
+ stbuf->f_flag = 0; /* don't have mount flags */
+ stbuf->f_namemax = 255; /* KDMaxFileNameLen% */
+
+ return 0;
+}
+
+struct fuse_operations plp_oper = {
+ .getattr = plp_getattr,
+ .access = plp_access,
+ .readlink = plp_readlink,
+ .readdir = plp_readdir,
+ .mknod = plp_mknod,
+ .mkdir = plp_mkdir,
+ .symlink = plp_symlink,
+ .unlink = plp_unlink,
+ .rmdir = plp_rmdir,
+ .rename = plp_rename,
+ .link = plp_link,
+ .chmod = plp_chmod,
+ .chown = plp_chown,
+ .truncate = plp_truncate,
+ .utimens = plp_utimens,
+ .open = plp_open,
+ .read = plp_read,
+ .write = plp_write,
+ .statfs = plp_statfs,
+};
diff --git a/plpfuse/main.cc b/plpfuse/main.cc
new file mode 100644
index 0000000..a6743b4
--- /dev/null
+++ b/plpfuse/main.cc
@@ -0,0 +1,380 @@
+/*-*-c++-*-
+ * $Id$
+ *
+ * This file is part of plptools.
+ *
+ * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
+ * Copyright (C) 2007 Reuben Thomas <rrt@sc3d.org>
+ *
+ * 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 <rfsv.h>
+#include <rpcs.h>
+#include <rfsvfactory.h>
+#include <rpcsfactory.h>
+#include <bufferstore.h>
+#include <bufferarray.h>
+#include <ppsocket.h>
+
+#include <iostream>
+#include <string>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "rfsv_api.h"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <getopt.h>
+
+using namespace std;
+
+static rfsv *a;
+static rfsvfactory *rf;
+
+static rpcs *r;
+static rpcsfactory *rp;
+static bufferStore owner;
+
+long rfsv_isalive() {
+ if (!a) {
+ if (!(a = rf->create(true)))
+ return 0;
+ }
+ return (a->getStatus() == rfsv::E_PSI_GEN_NONE);
+}
+
+long rfsv_dir(const char *file, dentry **e) {
+ PlpDir entries;
+ dentry *tmp;
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->dir(file, entries);
+
+ for (int i = 0; i < entries.size(); i++) {
+ PlpDirent pe = entries[i];
+ tmp = *e;
+ *e = (dentry *)calloc(1, sizeof(dentry));
+ if (!*e)
+ return -1;
+ (*e)->time = pe.getPsiTime().getTime();
+ (*e)->size = pe.getSize();
+ (*e)->attr = pe.getAttr();
+ (*e)->name = strdup(pe.getName());
+ (*e)->next = tmp;
+ }
+ return ret;
+}
+
+long rfsv_dircount(const char *file, u_int32_t *count) {
+ if (!a)
+ return -1;
+ return a->dircount(file, *count);
+}
+
+long rfsv_rmdir(const char *name) {
+ if (!a)
+ return -1;
+ return a->rmdir(name);
+}
+
+long rfsv_mkdir(const char *file) {
+ if (!a)
+ return -1;
+ return a->mkdir(file);
+}
+
+long rfsv_remove(const char *file) {
+ if (!a)
+ return -1;
+ return a->remove(file);
+}
+
+long rfsv_fclose(long handle) {
+ if (!a)
+ return -1;
+ return a->fclose(handle);
+}
+
+long rfsv_fcreate(long attr, const char *file, u_int32_t *handle) {
+ u_int32_t ph;
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->fcreatefile(attr, file, ph);
+ *handle = ph;
+ return ret;
+}
+
+long rfsv_open(const char *name, long mode, u_int32_t *handle) {
+ long ret, retry;
+
+ if (!a)
+ return -1;
+ if (mode == O_RDONLY)
+ mode = rfsv::PSI_O_RDONLY;
+ else
+ mode = rfsv::PSI_O_RDWR;
+ for (retry = 100; retry > 0 && (ret = a->fopen(a->opMode(mode), name, *handle)) != rfsv::E_PSI_GEN_NONE; retry--)
+ usleep(20000);
+ return ret;
+}
+
+long rfsv_read(char *buf, long offset, long len, const char *name) {
+ u_int32_t ret = 0, r_offset, handle;
+
+ if (!a)
+ return -1;
+ if ((ret = rfsv_open(name, O_RDONLY, &handle)))
+ return ret;
+ if (a->fseek(handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE ||
+ offset != r_offset ||
+ a->fread(handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE)
+ ret = -1;
+ rfsv_fclose(handle);
+ return ret;
+}
+
+long rfsv_write(const char *buf, long offset, long len, const char *name) {
+ u_int32_t ret = 0, r_offset, handle;
+
+ if (!a)
+ return -1;
+ if ((ret = rfsv_open(name, O_RDWR, &handle)))
+ return ret;
+ if (a->fseek(handle, offset, rfsv::PSI_SEEK_SET, r_offset) != rfsv::E_PSI_GEN_NONE ||
+ offset != r_offset ||
+ a->fwrite(handle, (unsigned char *)buf, len, ret) != rfsv::E_PSI_GEN_NONE)
+ ret = -1;
+ rfsv_fclose(handle);
+ return ret;
+}
+
+long rfsv_setmtime(const char *name, long time) {
+ if (!a)
+ return -1;
+ return a->fsetmtime(name, PsiTime(time));
+}
+
+long rfsv_setsize(const char *name, long size) {
+ u_int32_t ph;
+ long ret;
+
+ if (!a)
+ return -1;
+ ret = a->fopen(a->opMode(rfsv::PSI_O_RDWR), name, ph);
+ if (!ret) {
+ ret = a->fsetsize(ph, size);
+ a->fclose(ph);
+ }
+ return ret;
+}
+
+long rfsv_setattr(const char *name, long sattr, long dattr) {
+ if (!a)
+ return -1;
+ return a->fsetattr(name, sattr, dattr);
+}
+
+long rfsv_getattr(const char *name, long *attr, long *size, long *time) {
+ long res;
+ PlpDirent e;
+
+ if (!a)
+ return -1;
+ res = a->fgeteattr(name, e);
+ *attr = e.getAttr();
+ *size = e.getSize();
+ *time = e.getPsiTime().getTime();
+ return res;
+}
+
+long rfsv_statdev(char letter) {
+ PlpDrive drive;
+
+ if (!a)
+ return -1;
+ return (a->devinfo(letter, drive) != rfsv::E_PSI_GEN_NONE);
+}
+
+long rfsv_rename(const char *oldname, const char *newname) {
+ if (!a)
+ return -1;
+ return a->rename(oldname, newname);
+}
+
+long rfsv_drivelist(int *cnt, device **dlist) {
+ *dlist = NULL;
+ u_int32_t devbits;
+ long ret;
+ int i;
+
+ if (!a)
+ return -1;
+ ret = a->devlist(devbits);
+ if (ret == 0)
+ for (i = 0; i < 26; i++) {
+ PlpDrive drive;
+
+ if ((devbits & 1) &&
+ ((a->devinfo(i + 'A', drive) == rfsv::E_PSI_GEN_NONE))) {
+
+ device *next = *dlist;
+ *dlist = (device *)malloc(sizeof(device));
+ (*dlist)->next = next;
+ (*dlist)->name = strdup(drive.getName().c_str());
+ (*dlist)->total = drive.getSize();
+ (*dlist)->free = drive.getSpace();
+ (*dlist)->letter = 'A' + i;
+ (*dlist)->attrib = drive.getMediaType();
+ (*cnt)++;
+ }
+ devbits >>= 1;
+ }
+ return ret;
+}
+
+static void
+help()
+{
+ cerr << _(
+ "Usage: plpfuse [OPTION...] MOUNTPOINT\n"
+ "\n"
+ "Supported options:\n"
+ "\n"
+ " -u, --user=USER Specify USER who owns mounted dir\n"
+ " -d, --debug Increase debugging\n"
+ " -h, --help Display this text\n"
+ " -V, --version Print version and exit\n"
+ " -p, --port=[HOST:]PORT Connect to port PORT on host HOST\n"
+ " Default for HOST is 127.0.0.1\n"
+ " Default for PORT is "
+ ) << DPORT << "\n\n";
+}
+
+static void
+usage() {
+ cerr << _("Try `plpfuse --help' for more information") << endl;
+}
+
+static struct option opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"debug", no_argument, 0, 'd'},
+ {"version", no_argument, 0, 'V'},
+ {"port", required_argument, 0, 'p'},
+ {"user", required_argument, 0, 'u'},
+ {NULL, 0, 0, 0 }
+};
+
+static void
+parse_destination(const char *arg, const char **host, int *port)
+{
+ if (!arg)
+ return;
+ // We don't want to modify argv, therefore copy it first ...
+ char *argcpy = strdup(arg);
+ char *pp = strchr(argcpy, ':');
+
+ if (pp) {
+ // host.domain:400
+ // 10.0.0.1:400
+ *pp ++= '\0';
+ *host = argcpy;
+ } else {
+ // 400
+ // host.domain
+ // host
+ // 10.0.0.1
+ if (strchr(argcpy, '.') || !isdigit(argcpy[0])) {
+ *host = argcpy;
+ pp = 0L;
+ } else
+ pp = argcpy;
+ }
+ if (pp)
+ *port = atoi(pp);
+}
+
+int main(int argc, char**argv) {
+ ppsocket *skt;
+ ppsocket *skt2;
+ const char *host = "127.0.0.1";
+ int sockNum = DPORT;
+ int status = 0;
+ int i, c;
+
+ struct servent *se = getservbyname("psion", "tcp");
+ endservent();
+ if (se != 0L)
+ sockNum = ntohs(se->s_port);
+
+// while ((c = getopt_long(argc, argv, "hVp:d", opts, NULL)) != -1) {
+// switch (c) {
+// case 'V':
+// cerr << _("plpfuse version ") << VERSION << endl;
+// return 0;
+// case 'h':
+// help();
+// break;
+// case 'd':
+// debug++;
+// break;
+// case 'p':
+// parse_destination(optarg, &host, &sockNum);
+// break;
+// }
+// }
+
+ skt = new ppsocket();
+ if (!skt->connect(host, sockNum)) {
+ cerr << "plpfuse: could not connect to ncpd" << endl;
+ status = 1;
+ }
+ skt2 = new ppsocket();
+ if (!skt2->connect(host, sockNum)) {
+ cerr << "plpfuse: could not connect to ncpd" << endl;
+ status = 1;
+ }
+ if (status == 0) {
+ rf = new rfsvfactory(skt);
+ rp = new rpcsfactory(skt2);
+ a = rf->create(true);
+ r = rp->create(true);
+ if (a != NULL && r != NULL)
+ debuglog("plpfuse: connected, status is %d", status);
+ else
+ debuglog("plpfuse: could not create rfsv or rpcs object, connect delayed");
+// for (i = 0; i < optind; i++)
+// argv[i + 1] = argv[i + optind];
+// argc -= optind - 1;
+ status = fuse_main(argc, argv, &plp_oper, NULL);
+ delete a;
+ delete r;
+ }
+ exit(status);
+}
diff --git a/plpfuse/plpfuse.h b/plpfuse/plpfuse.h
new file mode 100644
index 0000000..c36d717
--- /dev/null
+++ b/plpfuse/plpfuse.h
@@ -0,0 +1,52 @@
+/* $Id$
+ *
+ */
+
+#ifndef _plpfuse_h_
+#define _plpfuse_h_
+
+#include <fuse.h>
+
+typedef struct p_inode {
+ int inode;
+ char *name;
+ struct p_inode *nextnam, *nextnum;
+} p_inode;
+
+/**
+ * Description of a Psion-Device
+ */
+typedef struct p_device {
+ char *name; /* Volume-Name */
+ char letter; /* Drive-Letter */
+ long attrib; /* Device-Attribs */
+ long total; /* Total capacity in bytes */
+ long free; /* Free space in bytes */
+ struct p_device *next;
+} device;
+
+/*
+ * Description of a Psion-File/Dir
+ */
+typedef struct p_dentry
+{
+ char *name;
+ long time;
+ long attr;
+ long size;
+ long links;
+ struct p_dentry *next;
+} dentry;
+
+extern int debug;
+
+extern int debuglog(char *fmt, ...);
+extern int errorlog(char *fmt, ...);
+extern int infolog(char *fmt, ...);
+
+#define BLOCKSIZE 512
+#define FID 7 /* File system id */
+
+#endif
+
+extern struct fuse_operations plp_oper;
diff --git a/plpfuse/rfsv_api.h b/plpfuse/rfsv_api.h
new file mode 100644
index 0000000..0fe4793
--- /dev/null
+++ b/plpfuse/rfsv_api.h
@@ -0,0 +1,76 @@
+/*-*-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
+ *
+ */
+#ifndef _rfsv_api_h_
+#define _rfsv_api_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "plpfuse.h"
+
+extern long rfsv_dir(const char *name, dentry **e);
+extern long rfsv_mkdir(const char *name);
+extern long rfsv_rmdir(const char *name);
+extern long rfsv_remove(const char *name);
+extern long rfsv_rename(const char *oldname, const char *newname);
+extern long rfsv_open(const char *name, long mode, u_int32_t *handle);
+extern long rfsv_fclose(long handle);
+extern long rfsv_fcreate(long attr, const char *name, u_int32_t *handle);
+extern long rfsv_read(char *buf, long offset, long len, const char *name);
+extern long rfsv_write(const char *buf, long offset, long len, const char *name);
+extern long rfsv_getattr(const char *name, long *attr, long *size, long *time);
+extern long rfsv_setattr(const char *name, long sattr, long dattr);
+extern long rfsv_setsize(const char *name, long size);
+extern long rfsv_setmtime(const char *name, long time);
+extern long rfsv_drivelist(int *cnt, device **devlist);
+extern long rfsv_dircount(const char *name, long *count);
+extern long rfsv_statdev(char letter);
+extern long rfsv_isalive();
+
+/* File attributes, C-style */
+#define PSI_A_RDONLY 0x0001
+#define PSI_A_HIDDEN 0x0002
+#define PSI_A_SYSTEM 0x0004
+#define PSI_A_DIR 0x0008
+#define PSI_A_ARCHIVE 0x0010
+#define PSI_A_VOLUME 0x0020
+#define PSI_A_NORMAL 0x0040
+#define PSI_A_TEMP 0x0080
+#define PSI_A_COMPRESSED 0x0100
+#define PSI_A_READ 0x0200
+#define PSI_A_EXEC 0x0400
+#define PSI_A_STREAM 0x0800
+#define PSI_A_TEXT 0x1000
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * End:
+ */