summaryrefslogtreecommitdiffstats
path: root/kioslave/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/nfs')
-rw-r--r--kioslave/nfs/AUTHORS2
-rw-r--r--kioslave/nfs/Makefile.am28
-rw-r--r--kioslave/nfs/README3
-rw-r--r--kioslave/nfs/TODO7
-rw-r--r--kioslave/nfs/kio_nfs.cpp1615
-rw-r--r--kioslave/nfs/kio_nfs.h109
-rw-r--r--kioslave/nfs/mount.h325
-rw-r--r--kioslave/nfs/mount.x255
-rw-r--r--kioslave/nfs/mount_xdr.c335
-rw-r--r--kioslave/nfs/nfs.protocol14
-rw-r--r--kioslave/nfs/nfs_prot.h699
-rw-r--r--kioslave/nfs/nfs_prot.x365
-rw-r--r--kioslave/nfs/nfs_prot_xdr.c886
13 files changed, 4643 insertions, 0 deletions
diff --git a/kioslave/nfs/AUTHORS b/kioslave/nfs/AUTHORS
new file mode 100644
index 000000000..062f9d6cb
--- /dev/null
+++ b/kioslave/nfs/AUTHORS
@@ -0,0 +1,2 @@
+Written and maintained by:
+Alexander Neundorf, neundorf@kde.org
diff --git a/kioslave/nfs/Makefile.am b/kioslave/nfs/Makefile.am
new file mode 100644
index 000000000..2c4fc062c
--- /dev/null
+++ b/kioslave/nfs/Makefile.am
@@ -0,0 +1,28 @@
+## Makefile.am of kdebase/kioslave/man
+
+INCLUDES= $(all_includes)
+AM_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+####### Files
+
+kde_module_LTLIBRARIES = kio_nfs.la
+
+kio_nfs_la_SOURCES = kio_nfs.cpp mount_xdr.c nfs_prot_xdr.c
+kio_nfs_la_LIBADD = -lkio $(LIBRPC)
+kio_nfs_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+noinst_HEADERS = nfs_prot.h mount.h
+
+kdelnk_DATA = nfs.protocol
+kdelnkdir = $(kde_servicesdir)
+
+METASOURCES = AUTO
+
+$(srcdir)/mount_xdr.c: $(srcdir)/mount.x
+ cd $(srcdir) && rpcgen ./mount.x
+
+
+$(srcdir)/nfs_prot_xdr.c: $(srcdir)/nfs_prot.x
+ cd $(srcdir) && rpcgen ./nfs_prot.x
+
+messages:
+ $(XGETTEXT) *.cpp -o $(podir)/kio_nfs.pot
diff --git a/kioslave/nfs/README b/kioslave/nfs/README
new file mode 100644
index 000000000..671934e2c
--- /dev/null
+++ b/kioslave/nfs/README
@@ -0,0 +1,3 @@
+this is an ioslave for KDE 2 for NFS, version 2.
+
+Alex
diff --git a/kioslave/nfs/TODO b/kioslave/nfs/TODO
new file mode 100644
index 000000000..6e5525127
--- /dev/null
+++ b/kioslave/nfs/TODO
@@ -0,0 +1,7 @@
+-symlink stuff (listing and stating works already)
+-honour the resume flag
+-maybe use rpcgen ?
+-cache handling: how long should file handles be cached ?
+ should the stat'ed structures be cached ? no, IMHO
+
+Alex
diff --git a/kioslave/nfs/kio_nfs.cpp b/kioslave/nfs/kio_nfs.cpp
new file mode 100644
index 000000000..18a7f1393
--- /dev/null
+++ b/kioslave/nfs/kio_nfs.cpp
@@ -0,0 +1,1615 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include <arpa/inet.h>
+
+// This is needed on Solaris so that rpc.h defines clnttcp_create etc.
+#ifndef PORTMAP
+#define PORTMAP
+#endif
+#include <rpc/rpc.h> // for rpc calls
+
+#include <errno.h>
+#include <grp.h>
+#include <memory.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qdir.h>
+
+#include <kdebug.h>
+#include <kinstance.h>
+#include <klocale.h>
+
+#include <kio/global.h>
+#include <iostream>
+
+#include "nfs_prot.h"
+#define fhandle _fhandle
+#include "mount.h"
+#include "kio_nfs.h"
+
+#define MAXHOSTLEN 256
+
+//#define MAXFHAGE 60*15 //15 minutes maximum age for file handles
+
+//this ioslave is for NFS version 2
+#define NFSPROG ((u_long)100003)
+#define NFSVERS ((u_long)2)
+
+using namespace KIO;
+using namespace std;
+
+//this is taken from kdelibs/kdecore/fakes.cpp
+//#if !defined(HAVE_GETDOMAINNAME)
+
+int x_getdomainname(char *name, size_t len)
+{
+ struct utsname uts;
+ struct hostent *hent;
+ int rv = -1;
+
+ if (name == 0L)
+ errno = EINVAL;
+ else
+ {
+ name[0] = '\0';
+ if (uname(&uts) >= 0)
+ {
+ if ((hent = gethostbyname(uts.nodename)) != 0L)
+ {
+ char *p = strchr(hent->h_name, '.');
+ if (p != 0L)
+ {
+ ++p;
+ if (strlen(p) > len-1)
+ errno = EINVAL;
+ else
+ {
+ strcpy(name, p);
+ rv = 0;
+ }
+ }
+ }
+ }
+ }
+ return rv;
+}
+//#endif
+
+
+extern "C" { int KDE_EXPORT kdemain(int argc, char **argv); }
+
+int kdemain( int argc, char **argv )
+{
+ KInstance instance( "kio_nfs" );
+
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: kio_nfs protocol domain-socket1 domain-socket2\n");
+ exit(-1);
+ }
+ kdDebug(7121) << "NFS: kdemain: starting" << endl;
+
+ NFSProtocol slave(argv[2], argv[3]);
+ slave.dispatchLoop();
+ return 0;
+}
+
+static bool isRoot(const QString& path)
+{
+ return (path.isEmpty() || (path=="/"));
+}
+
+static bool isAbsoluteLink(const QString& path)
+{
+ //hmm, don't know
+ if (path.isEmpty()) return TRUE;
+ if (path[0]=='/') return TRUE;
+ return FALSE;
+}
+
+static void createVirtualDirEntry(UDSEntry & entry)
+{
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_USER;
+ atom.m_str = "root";
+ entry.append( atom );
+ atom.m_uds = KIO::UDS_GROUP;
+ atom.m_str = "root";
+ entry.append( atom );
+
+ //a dummy size
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 1024;
+ entry.append( atom );
+}
+
+
+static void stripTrailingSlash(QString& path)
+{
+ //if (path=="/") return;
+ if (path=="/") path="";
+ else if (path[path.length()-1]=='/') path.truncate(path.length()-1);
+}
+
+static void getLastPart(const QString& path, QString& lastPart, QString& rest)
+{
+ int slashPos=path.findRev("/");
+ lastPart=path.mid(slashPos+1);
+ rest=path.left(slashPos+1);
+}
+
+static QString removeFirstPart(const QString& path)
+{
+ QString result("");
+ if (path.isEmpty()) return result;
+ result=path.mid(1);
+ int slashPos=result.find("/");
+ return result.mid(slashPos+1);
+}
+
+NFSFileHandle::NFSFileHandle()
+:m_isInvalid(FALSE)
+{
+ memset(m_handle,'\0',NFS_FHSIZE+1);
+// m_detectTime=time(0);
+}
+
+NFSFileHandle::NFSFileHandle(const NFSFileHandle & handle)
+:m_isInvalid(FALSE)
+{
+ m_handle[NFS_FHSIZE]='\0';
+ memcpy(m_handle,handle.m_handle,NFS_FHSIZE);
+ m_isInvalid=handle.m_isInvalid;
+// m_detectTime=handle.m_detectTime;
+}
+
+NFSFileHandle::~NFSFileHandle()
+{}
+
+NFSFileHandle& NFSFileHandle::operator= (const NFSFileHandle& src)
+{
+ memcpy(m_handle,src.m_handle,NFS_FHSIZE);
+ m_isInvalid=src.m_isInvalid;
+// m_detectTime=src.m_detectTime;
+ return *this;
+}
+
+NFSFileHandle& NFSFileHandle::operator= (const char* src)
+{
+ if (src==0)
+ {
+ m_isInvalid=TRUE;
+ return *this;
+ };
+ memcpy(m_handle,src,NFS_FHSIZE);
+ m_isInvalid=FALSE;
+// m_detectTime=time(0);
+ return *this;
+}
+
+/*time_t NFSFileHandle::age() const
+{
+ return (time(0)-m_detectTime);
+}*/
+
+
+NFSProtocol::NFSProtocol (const QCString &pool, const QCString &app )
+:SlaveBase( "nfs", pool, app )
+,m_client(0)
+,m_sock(-1)
+,m_lastCheck(time(0))
+{
+ kdDebug(7121)<<"NFS::NFS: -"<<pool<<"-"<<endl;
+}
+
+NFSProtocol::~NFSProtocol()
+{
+ closeConnection();
+}
+
+/*This one is currently unused, so it could be removed.
+ The intention was to keep handles around, and from time to time
+ remove handles which are too old. Alex
+ */
+/*void NFSProtocol::checkForOldFHs()
+{
+ kdDebug(7121)<<"checking for fhs older than "<<MAXFHAGE<<endl;
+ kdDebug(7121)<<"current items: "<<m_handleCache.count()<<endl;
+ NFSFileHandleMap::Iterator it=m_handleCache.begin();
+ NFSFileHandleMap::Iterator lastIt=it;
+ while (it!=m_handleCache.end())
+ {
+ kdDebug(7121)<<it.data().age()<<flush;
+ if (it.data().age()>MAXFHAGE)
+ {
+ kdDebug(7121)<<"removing"<<endl;
+ m_handleCache.remove(it);
+ if (it==lastIt)
+ {
+ it=m_handleCache.begin();
+ lastIt=it;
+ }
+ else
+ it=lastIt;
+ }
+ lastIt=it;
+ it++;
+ };
+ kdDebug(7121)<<"left items: "<<m_handleCache.count()<<endl;
+ m_lastCheck=time(0);
+}*/
+
+void NFSProtocol::closeConnection()
+{
+ close(m_sock);
+ m_sock=-1;
+ if (m_client==0) return;
+ CLNT_DESTROY(m_client);
+
+ m_client=0;
+}
+
+bool NFSProtocol::isExportedDir(const QString& path)
+{
+ return (m_exportedDirs.find(path.mid(1))!=m_exportedDirs.end());
+}
+
+/* This one works recursive.
+ It tries to get the file handle out of the file handle cache.
+ If this doesn't succeed, it needs to do a nfs rpc call
+ in order to obtain one.
+ */
+NFSFileHandle NFSProtocol::getFileHandle(QString path)
+{
+ if (m_client==0) openConnection();
+
+ //I'm not sure if this is useful
+ //if ((time(0)-m_lastCheck)>MAXFHAGE) checkForOldFHs();
+
+ stripTrailingSlash(path);
+ kdDebug(7121)<<"getting FH for -"<<path<<"-"<<endl;
+ //now the path looks like "/root/some/dir" or "" if it was "/"
+ NFSFileHandle parentFH;
+ //we didn't find it
+ if (path.isEmpty())
+ {
+ kdDebug(7121)<<"path is empty, invalidating the FH"<<endl;
+ parentFH.setInvalid();
+ return parentFH;
+ }
+ //check wether we have this filehandle cached
+ //the filehandles of the exported root dirs are always in the cache
+ if (m_handleCache.find(path)!=m_handleCache.end())
+ {
+ kdDebug(7121)<<"path is in the cache, returning the FH -"<<m_handleCache[path]<<"-"<<endl;
+ return m_handleCache[path];
+ }
+ QString rest, lastPart;
+ getLastPart(path,lastPart,rest);
+ kdDebug(7121)<<"splitting path into rest -"<<rest<<"- and lastPart -"<<lastPart<<"-"<<endl;
+
+ parentFH=getFileHandle(rest);
+ //f*ck, it's invalid
+ if (parentFH.isInvalid())
+ {
+ kdDebug(7121)<<"the parent FH is invalid"<<endl;
+ return parentFH;
+ }
+ // do the rpc call
+ diropargs dirargs;
+ diropres dirres;
+ memcpy(dirargs.dir.data,(const char*)parentFH,NFS_FHSIZE);
+ QCString tmpStr=QFile::encodeName(lastPart);
+ dirargs.name=tmpStr.data();
+
+ //cerr<<"calling rpc: FH: -"<<parentFH<<"- with name -"<<dirargs.name<<"-"<<endl;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_LOOKUP,
+ (xdrproc_t) xdr_diropargs, (char*)&dirargs,
+ (xdrproc_t) xdr_diropres, (char*)&dirres,total_timeout);
+
+ if ((clnt_stat!=RPC_SUCCESS) || (dirres.status!=NFS_OK))
+ {
+ //we failed
+ kdDebug(7121)<<"lookup of filehandle failed"<<endl;
+ parentFH.setInvalid();
+ return parentFH;
+ }
+ //everything went fine up to now :-)
+ parentFH=dirres.diropres_u.diropres.file.data;
+ //kdDebug(7121)<<"filesize: "<<dirres.diropres_u.diropres.attributes.size<<endl;
+ m_handleCache.insert(path,parentFH);
+ kdDebug(7121)<<"return FH -"<<parentFH<<"-"<<endl;
+ return parentFH;
+}
+
+/* Open connection connects to the mount daemon on the server side.
+ In order to do this it needs authentication and calls auth_unix_create().
+ Then it asks the mount daemon for the exported shares. Then it tries
+ to mount all these shares. If this succeeded for at least one of them,
+ a client for the nfs daemon is created.
+ */
+void NFSProtocol::openConnection()
+{
+ kdDebug(7121)<<"NFS::openConnection for -" << m_currentHost.latin1() << "-" << endl;
+ if (m_currentHost.isEmpty())
+ {
+ error(ERR_UNKNOWN_HOST,"");
+ return;
+ }
+ struct sockaddr_in server_addr;
+ if (m_currentHost[0] >= '0' && m_currentHost[0] <= '9')
+ {
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = inet_addr(m_currentHost.latin1());
+ }
+ else
+ {
+ struct hostent *hp=gethostbyname(m_currentHost.latin1());
+ if (hp==0)
+ {
+ error( ERR_UNKNOWN_HOST, m_currentHost.latin1() );
+ return;
+ }
+ server_addr.sin_family = AF_INET;
+ memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ }
+
+ // create mount deamon client
+ closeConnection();
+ server_addr.sin_port = 0;
+ m_sock = RPC_ANYSOCK;
+ m_client=clnttcp_create(&server_addr,MOUNTPROG, MOUNTVERS, &m_sock, 0, 0);
+ if (m_client==0)
+ {
+ server_addr.sin_port = 0;
+ m_sock = RPC_ANYSOCK;
+ pertry_timeout.tv_sec = 3;
+ pertry_timeout.tv_usec = 0;
+ m_client = clntudp_create(&server_addr,MOUNTPROG, MOUNTVERS, pertry_timeout, &m_sock);
+ if (m_client==0)
+ {
+ clnt_pcreateerror(const_cast<char *>("mount clntudp_create"));
+ error(ERR_COULD_NOT_CONNECT, m_currentHost.latin1());
+ return;
+ }
+ }
+ QCString hostName("localhost");
+ char nameBuffer[1024];
+ nameBuffer[0] = '\0';
+ if (gethostname(nameBuffer, 1024)==0)
+ {
+ nameBuffer[sizeof(nameBuffer)-1] = '\0';
+ hostName=nameBuffer;
+ // I have the same problem here as Stefan Westerfeld, that's why I use
+ // the getdomainname() from fakes.cpp (renamed to x_getdomainname()), this one works
+ // taken from kdelibs/arts/mcopy/mcoputils.cc
+ nameBuffer[0] = '\0';
+ if (x_getdomainname(nameBuffer, 1024)==0)
+ {
+ nameBuffer[sizeof(nameBuffer)-1] = '\0';
+ /*
+ * I don't know why, but on my linux machine, the domainname
+ * always ends up being (none), which is certainly no valid
+ * domainname
+ */
+ if(strcmp(nameBuffer,"(none)") != 0) {
+ hostName += ".";
+ hostName += nameBuffer;
+ }
+ }
+ }
+ kdDebug(7121) << "hostname is -" << hostName << "-" << endl;
+ m_client->cl_auth = authunix_create(hostName.data(), geteuid(), getegid(), 0, 0);
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+
+ exports exportlist;
+ //now do the stuff
+ memset(&exportlist, '\0', sizeof(exportlist));
+
+ int clnt_stat = clnt_call(m_client, MOUNTPROC_EXPORT,(xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_exports, (char*)&exportlist,total_timeout);
+ if (!checkForError(clnt_stat, 0, m_currentHost.latin1())) return;
+
+ fhstatus fhStatus;
+ bool atLeastOnceSucceeded(FALSE);
+ for(; exportlist!=0;exportlist = exportlist->ex_next) {
+ kdDebug(7121) << "found export: " << exportlist->ex_dir << endl;
+
+ memset(&fhStatus, 0, sizeof(fhStatus));
+ clnt_stat = clnt_call(m_client, MOUNTPROC_MNT,(xdrproc_t) xdr_dirpath, (char*)(&(exportlist->ex_dir)),
+ (xdrproc_t) xdr_fhstatus,(char*) &fhStatus,total_timeout);
+ if (fhStatus.fhs_status==0) {
+ atLeastOnceSucceeded=TRUE;
+ NFSFileHandle fh;
+ fh=fhStatus.fhstatus_u.fhs_fhandle;
+ QString fname;
+ if ( exportlist->ex_dir[0] == '/' )
+ fname = KIO::encodeFileName(exportlist->ex_dir + 1);
+ else
+ fname = KIO::encodeFileName(exportlist->ex_dir);
+ m_handleCache.insert(QString("/")+fname,fh);
+ m_exportedDirs.append(fname);
+ // kdDebug() <<"appending file -"<<fname<<"- with FH: -"<<fhStatus.fhstatus_u.fhs_fhandle<<"-"<<endl;
+ }
+ }
+ if (!atLeastOnceSucceeded)
+ {
+ closeConnection();
+ error( ERR_COULD_NOT_AUTHENTICATE, m_currentHost.latin1());
+ return;
+ }
+ server_addr.sin_port = 0;
+
+ //now create the client for the nfs daemon
+ //first get rid of the old one
+ closeConnection();
+ m_sock = RPC_ANYSOCK;
+ m_client = clnttcp_create(&server_addr,NFSPROG,NFSVERS,&m_sock,0,0);
+ if (m_client == 0)
+ {
+ server_addr.sin_port = 0;
+ m_sock = RPC_ANYSOCK;
+ pertry_timeout.tv_sec = 3;
+ pertry_timeout.tv_usec = 0;
+ m_client = clntudp_create(&server_addr,NFSPROG, NFSVERS, pertry_timeout, &m_sock);
+ if (m_client==0)
+ {
+ clnt_pcreateerror(const_cast<char *>("NFS clntudp_create"));
+ error(ERR_COULD_NOT_CONNECT, m_currentHost.latin1());
+ return;
+ }
+ }
+ m_client->cl_auth = authunix_create(hostName.data(),geteuid(),getegid(),0,0);
+ connected();
+ kdDebug(7121)<<"openConnection succeeded"<<endl;
+}
+
+void NFSProtocol::listDir( const KURL& _url)
+{
+ KURL url(_url);
+ QString path( QFile::encodeName(url.path()));
+
+ if (path.isEmpty())
+ {
+ url.setPath("/");
+ redirection(url);
+ finished();
+ return;
+ }
+ //open the connection
+ if (m_client==0) openConnection();
+ //it failed
+ if (m_client==0) return;
+ if (isRoot(path))
+ {
+ kdDebug(7121)<<"listing root"<<endl;
+ totalSize( m_exportedDirs.count());
+ //in this case we don't need to do a real listdir
+ UDSEntry entry;
+ for (QStringList::Iterator it=m_exportedDirs.begin(); it!=m_exportedDirs.end(); it++)
+ {
+ UDSAtom atom;
+ entry.clear();
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = (*it);
+ kdDebug(7121)<<"listing "<<(*it)<<endl;
+ entry.append( atom );
+ createVirtualDirEntry(entry);
+ listEntry( entry, false);
+ }
+ listEntry( entry, true ); // ready
+ finished();
+ return;
+ }
+
+ QStringList filesToList;
+ kdDebug(7121)<<"getting subdir -"<<path<<"-"<<endl;
+ stripTrailingSlash(path);
+ NFSFileHandle fh=getFileHandle(path);
+ //cerr<<"this is the fh: -"<<fh<<"-"<<endl;
+ if (fh.isInvalid())
+ {
+ error( ERR_DOES_NOT_EXIST, path);
+ return;
+ }
+ readdirargs listargs;
+ memset(&listargs,0,sizeof(listargs));
+ listargs.count=1024*16;
+ memcpy(listargs.dir.data,fh,NFS_FHSIZE);
+ readdirres listres;
+ do
+ {
+ memset(&listres,'\0',sizeof(listres));
+ int clnt_stat = clnt_call(m_client, NFSPROC_READDIR, (xdrproc_t) xdr_readdirargs, (char*)&listargs,
+ (xdrproc_t) xdr_readdirres, (char*)&listres,total_timeout);
+ if (!checkForError(clnt_stat,listres.status,path)) return;
+ for (entry *dirEntry=listres.readdirres_u.reply.entries;dirEntry!=0;dirEntry=dirEntry->nextentry)
+ {
+ if ((QString(".")!=dirEntry->name) && (QString("..")!=dirEntry->name))
+ filesToList.append(dirEntry->name);
+ }
+ } while (!listres.readdirres_u.reply.eof);
+ totalSize( filesToList.count());
+
+ UDSEntry entry;
+ //stat all files in filesToList
+ for (QStringList::Iterator it=filesToList.begin(); it!=filesToList.end(); it++)
+ {
+ UDSAtom atom;
+ diropargs dirargs;
+ diropres dirres;
+ memcpy(dirargs.dir.data,fh,NFS_FHSIZE);
+ QCString tmpStr=QFile::encodeName(*it);
+ dirargs.name=tmpStr.data();
+
+ kdDebug(7121)<<"calling rpc: FH: -"<<fh<<"- with name -"<<dirargs.name<<"-"<<endl;
+
+ int clnt_stat= clnt_call(m_client, NFSPROC_LOOKUP,
+ (xdrproc_t) xdr_diropargs, (char*)&dirargs,
+ (xdrproc_t) xdr_diropres, (char*)&dirres,total_timeout);
+ if (!checkForError(clnt_stat,dirres.status,(*it))) return;
+
+ NFSFileHandle tmpFH;
+ tmpFH=dirres.diropres_u.diropres.file.data;
+ m_handleCache.insert(path+"/"+(*it),tmpFH);
+
+ entry.clear();
+
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = (*it);
+ entry.append( atom );
+
+ //is it a symlink ?
+ if (S_ISLNK(dirres.diropres_u.diropres.attributes.mode))
+ {
+ kdDebug(7121)<<"it's a symlink !"<<endl;
+ //cerr<<"fh: "<<tmpFH<<endl;
+ nfs_fh nfsFH;
+ memcpy(nfsFH.data,dirres.diropres_u.diropres.file.data,NFS_FHSIZE);
+ //get the link dest
+ readlinkres readLinkRes;
+ char nameBuf[NFS_MAXPATHLEN];
+ readLinkRes.readlinkres_u.data=nameBuf;
+ int clnt_stat=clnt_call(m_client, NFSPROC_READLINK,
+ (xdrproc_t) xdr_nfs_fh, (char*)&nfsFH,
+ (xdrproc_t) xdr_readlinkres, (char*)&readLinkRes,total_timeout);
+ if (!checkForError(clnt_stat,readLinkRes.status,(*it))) return;
+ kdDebug(7121)<<"link dest is -"<<readLinkRes.readlinkres_u.data<<"-"<<endl;
+ QCString linkDest(readLinkRes.readlinkres_u.data);
+ atom.m_uds = KIO::UDS_LINK_DEST;
+ atom.m_str = linkDest;
+ entry.append( atom );
+
+ bool isValid=isValidLink(path,linkDest);
+ if (!isValid)
+ {
+ completeBadLinkUDSEntry(entry,dirres.diropres_u.diropres.attributes);
+ }
+ else
+ {
+ if (isAbsoluteLink(linkDest))
+ {
+ completeAbsoluteLinkUDSEntry(entry,linkDest);
+ }
+ else
+ {
+ tmpStr=QDir::cleanDirPath(path+QString("/")+QString(linkDest)).latin1();
+ dirargs.name=tmpStr.data();
+ tmpFH=getFileHandle(tmpStr);
+ memcpy(dirargs.dir.data,tmpFH,NFS_FHSIZE);
+
+ attrstat attrAndStat;
+
+ kdDebug(7121)<<"calling rpc: FH: -"<<fh<<"- with name -"<<dirargs.name<<"-"<<endl;
+
+ clnt_stat = clnt_call(m_client, NFSPROC_GETATTR,
+ (xdrproc_t) xdr_diropargs, (char*)&dirargs,
+ (xdrproc_t) xdr_attrstat, (char*)&attrAndStat,total_timeout);
+ if (!checkForError(clnt_stat,attrAndStat.status,tmpStr)) return;
+ completeUDSEntry(entry,attrAndStat.attrstat_u.attributes);
+ }
+ }
+ }
+ else
+ completeUDSEntry(entry,dirres.diropres_u.diropres.attributes);
+ listEntry( entry, false);
+ }
+ listEntry( entry, true ); // ready
+ finished();
+}
+
+void NFSProtocol::stat( const KURL & url)
+{
+ QString path( QFile::encodeName(url.path()));
+ stripTrailingSlash(path);
+ kdDebug(7121)<<"NFS::stat for -"<<path<<"-"<<endl;
+ QString tmpPath=path;
+ if ((tmpPath.length()>1) && (tmpPath[0]=='/')) tmpPath=tmpPath.mid(1);
+ // We can't stat root, but we know it's a dir
+ if (isRoot(path) || isExportedDir(path))
+ {
+ UDSEntry entry;
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = path;
+ entry.append( atom );
+ createVirtualDirEntry(entry);
+ // no size
+ statEntry( entry );
+ finished();
+ kdDebug(7121)<<"succeeded"<<endl;
+ return;
+ }
+
+ NFSFileHandle fh=getFileHandle(path);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,path);
+ return;
+ }
+
+ diropargs dirargs;
+ attrstat attrAndStat;
+ memcpy(dirargs.dir.data,fh,NFS_FHSIZE);
+ QCString tmpStr=QFile::encodeName(path);
+ dirargs.name=tmpStr.data();
+
+ kdDebug(7121)<<"calling rpc: FH: -"<<fh<<"- with name -"<<dirargs.name<<"-"<<endl;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_GETATTR,
+ (xdrproc_t) xdr_diropargs, (char*)&dirargs,
+ (xdrproc_t) xdr_attrstat, (char*)&attrAndStat,total_timeout);
+ if (!checkForError(clnt_stat,attrAndStat.status,path)) return;
+ UDSEntry entry;
+ entry.clear();
+
+ UDSAtom atom;
+
+ QString fileName, parentDir;
+ getLastPart(path, fileName, parentDir);
+ stripTrailingSlash(parentDir);
+
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = fileName;
+ entry.append( atom );
+
+ //is it a symlink ?
+ if (S_ISLNK(attrAndStat.attrstat_u.attributes.mode))
+ {
+ kdDebug(7121)<<"it's a symlink !"<<endl;
+ nfs_fh nfsFH;
+ memcpy(nfsFH.data,fh,NFS_FHSIZE);
+ //get the link dest
+ readlinkres readLinkRes;
+ char nameBuf[NFS_MAXPATHLEN];
+ readLinkRes.readlinkres_u.data=nameBuf;
+
+ int clnt_stat=clnt_call(m_client, NFSPROC_READLINK,
+ (xdrproc_t) xdr_nfs_fh, (char*)&nfsFH,
+ (xdrproc_t) xdr_readlinkres, (char*)&readLinkRes,total_timeout);
+ if (!checkForError(clnt_stat,readLinkRes.status,path)) return;
+ kdDebug(7121)<<"link dest is -"<<readLinkRes.readlinkres_u.data<<"-"<<endl;
+ QCString linkDest(readLinkRes.readlinkres_u.data);
+ atom.m_uds = KIO::UDS_LINK_DEST;
+ atom.m_str = linkDest;
+ entry.append( atom );
+
+ bool isValid=isValidLink(parentDir,linkDest);
+ if (!isValid)
+ {
+ completeBadLinkUDSEntry(entry,attrAndStat.attrstat_u.attributes);
+ }
+ else
+ {
+ if (isAbsoluteLink(linkDest))
+ {
+ completeAbsoluteLinkUDSEntry(entry,linkDest);
+ }
+ else
+ {
+
+ tmpStr=QDir::cleanDirPath(parentDir+QString("/")+QString(linkDest)).latin1();
+ diropargs dirargs;
+ dirargs.name=tmpStr.data();
+ NFSFileHandle tmpFH;
+ tmpFH=getFileHandle(tmpStr);
+ memcpy(dirargs.dir.data,tmpFH,NFS_FHSIZE);
+
+ kdDebug(7121)<<"calling rpc: FH: -"<<fh<<"- with name -"<<dirargs.name<<"-"<<endl;
+ clnt_stat = clnt_call(m_client, NFSPROC_GETATTR,
+ (xdrproc_t) xdr_diropargs, (char*)&dirargs,
+ (xdrproc_t) xdr_attrstat, (char*)&attrAndStat,total_timeout);
+ if (!checkForError(clnt_stat,attrAndStat.status,tmpStr)) return;
+ completeUDSEntry(entry,attrAndStat.attrstat_u.attributes);
+ }
+ }
+ }
+ else
+ completeUDSEntry(entry,attrAndStat.attrstat_u.attributes);
+ statEntry( entry );
+ finished();
+}
+
+void NFSProtocol::completeAbsoluteLinkUDSEntry(UDSEntry& entry, const QCString& path)
+{
+ //taken from file.cc
+ struct stat buff;
+ if ( ::stat( path.data(), &buff ) == -1 ) return;
+
+ UDSAtom atom;
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = buff.st_mode & S_IFMT; // extract file type
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = buff.st_mode & 07777; // extract permissions
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = buff.st_size;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_MODIFICATION_TIME;
+ atom.m_long = buff.st_mtime;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_USER;
+ uid_t uid = buff.st_uid;
+ QString *temp = m_usercache.find( uid );
+
+ if ( !temp )
+ {
+ struct passwd *user = getpwuid( uid );
+ if ( user )
+ {
+ m_usercache.insert( uid, new QString(QString::fromLatin1(user->pw_name)) );
+ atom.m_str = user->pw_name;
+ }
+ else
+ atom.m_str = "???";
+ }
+ else
+ atom.m_str = *temp;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_GROUP;
+ gid_t gid = buff.st_gid;
+ temp = m_groupcache.find( gid );
+ if ( !temp )
+ {
+ struct group *grp = getgrgid( gid );
+ if ( grp )
+ {
+ m_groupcache.insert( gid, new QString(QString::fromLatin1(grp->gr_name)) );
+ atom.m_str = grp->gr_name;
+ }
+ else
+ atom.m_str = "???";
+ }
+ else
+ atom.m_str = *temp;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS_TIME;
+ atom.m_long = buff.st_atime;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_CREATION_TIME;
+ atom.m_long = buff.st_ctime;
+ entry.append( atom );
+}
+
+void NFSProtocol::completeBadLinkUDSEntry(UDSEntry& entry, fattr& attributes)
+{
+ // It is a link pointing to nowhere
+ completeUDSEntry(entry,attributes);
+
+ UDSAtom atom;
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFMT - 1;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRWXU | S_IRWXG | S_IRWXO;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 0L;
+ entry.append( atom );
+}
+
+void NFSProtocol::completeUDSEntry(UDSEntry& entry, fattr& attributes)
+{
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = attributes.size;
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_MODIFICATION_TIME;
+ atom.m_long = attributes.mtime.seconds;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS_TIME;
+ atom.m_long = attributes.atime.seconds;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_CREATION_TIME;
+ atom.m_long = attributes.ctime.seconds;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = (attributes.mode & 07777);
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long =attributes.mode & S_IFMT; // extract file type
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_USER;
+ uid_t uid = attributes.uid;
+ QString *temp = m_usercache.find( uid );
+ if ( !temp )
+ {
+ struct passwd *user = getpwuid( uid );
+ if ( user )
+ {
+ m_usercache.insert( uid, new QString(user->pw_name) );
+ atom.m_str = user->pw_name;
+ }
+ else
+ atom.m_str = "???";
+ }
+ else
+ atom.m_str = *temp;
+ entry.append( atom );
+
+ atom.m_uds = KIO::UDS_GROUP;
+ gid_t gid = attributes.gid;
+ temp = m_groupcache.find( gid );
+ if ( !temp )
+ {
+ struct group *grp = getgrgid( gid );
+ if ( grp )
+ {
+ m_groupcache.insert( gid, new QString(grp->gr_name) );
+ atom.m_str = grp->gr_name;
+ }
+ else
+ atom.m_str = "???";
+ }
+ else
+ atom.m_str = *temp;
+ entry.append( atom );
+
+/* KIO::UDSEntry::ConstIterator it = entry.begin();
+ for( ; it != entry.end(); it++ ) {
+ switch ((*it).m_uds) {
+ case KIO::UDS_FILE_TYPE:
+ kdDebug(7121) << "File Type : " << (mode_t)((*it).m_long) << endl;
+ break;
+ case KIO::UDS_ACCESS:
+ kdDebug(7121) << "Access permissions : " << (mode_t)((*it).m_long) << endl;
+ break;
+ case KIO::UDS_USER:
+ kdDebug(7121) << "User : " << ((*it).m_str.ascii() ) << endl;
+ break;
+ case KIO::UDS_GROUP:
+ kdDebug(7121) << "Group : " << ((*it).m_str.ascii() ) << endl;
+ break;
+ case KIO::UDS_NAME:
+ kdDebug(7121) << "Name : " << ((*it).m_str.ascii() ) << endl;
+ //m_strText = decodeFileName( (*it).m_str );
+ break;
+ case KIO::UDS_URL:
+ kdDebug(7121) << "URL : " << ((*it).m_str.ascii() ) << endl;
+ break;
+ case KIO::UDS_MIME_TYPE:
+ kdDebug(7121) << "MimeType : " << ((*it).m_str.ascii() ) << endl;
+ break;
+ case KIO::UDS_LINK_DEST:
+ kdDebug(7121) << "LinkDest : " << ((*it).m_str.ascii() ) << endl;
+ break;
+ }
+ }*/
+}
+
+void NFSProtocol::setHost(const QString& host, int /*port*/, const QString& /*user*/, const QString& /*pass*/)
+{
+ kdDebug(7121)<<"setHost: -"<<host<<"-"<<endl;
+ if (host.isEmpty())
+ {
+ error(ERR_UNKNOWN_HOST,"");
+ return;
+ }
+ if (host==m_currentHost) return;
+ m_currentHost=host;
+ m_handleCache.clear();
+ m_exportedDirs.clear();
+ closeConnection();
+}
+
+void NFSProtocol::mkdir( const KURL& url, int permissions )
+{
+ kdDebug(7121)<<"mkdir"<<endl;
+ QString thePath( QFile::encodeName(url.path()));
+ stripTrailingSlash(thePath);
+ QString dirName, parentDir;
+ getLastPart(thePath, dirName, parentDir);
+ stripTrailingSlash(parentDir);
+ kdDebug(7121)<<"path: -"<<thePath<<"- dir: -"<<dirName<<"- parentDir: -"<<parentDir<<"-"<<endl;
+ if (isRoot(parentDir))
+ {
+ error(ERR_WRITE_ACCESS_DENIED,thePath);
+ return;
+ }
+ NFSFileHandle fh=getFileHandle(parentDir);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,thePath);
+ return;
+ }
+
+ createargs createArgs;
+ memcpy(createArgs.where.dir.data,fh,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(dirName);
+ createArgs.where.name=tmpName.data();
+ if (permissions==-1) createArgs.attributes.mode=0755;
+ else createArgs.attributes.mode=permissions;
+
+ diropres dirres;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_MKDIR,
+ (xdrproc_t) xdr_createargs, (char*)&createArgs,
+ (xdrproc_t) xdr_diropres, (char*)&dirres,total_timeout);
+ if (!checkForError(clnt_stat,dirres.status,thePath)) return;
+ finished();
+}
+
+bool NFSProtocol::checkForError(int clientStat, int nfsStat, const QString& text)
+{
+ if (clientStat!=RPC_SUCCESS)
+ {
+ kdDebug(7121)<<"rpc error: "<<clientStat<<endl;
+ //does this mapping make sense ?
+ error(ERR_CONNECTION_BROKEN,i18n("An RPC error occurred."));
+ return FALSE;
+ }
+ if (nfsStat!=NFS_OK)
+ {
+ kdDebug(7121)<<"nfs error: "<<nfsStat<<endl;
+ switch (nfsStat)
+ {
+ case NFSERR_PERM:
+ error(ERR_ACCESS_DENIED,text);
+ break;
+ case NFSERR_NOENT:
+ error(ERR_DOES_NOT_EXIST,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_IO:
+ error(ERR_INTERNAL_SERVER,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_NXIO:
+ error(ERR_DOES_NOT_EXIST,text);
+ break;
+ case NFSERR_ACCES:
+ error(ERR_ACCESS_DENIED,text);
+ break;
+ case NFSERR_EXIST:
+ error(ERR_FILE_ALREADY_EXIST,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_NODEV:
+ error(ERR_DOES_NOT_EXIST,text);
+ break;
+ case NFSERR_NOTDIR:
+ error(ERR_IS_FILE,text);
+ break;
+ case NFSERR_ISDIR:
+ error(ERR_IS_DIRECTORY,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_FBIG:
+ error(ERR_INTERNAL_SERVER,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_NOSPC:
+ error(ERR_INTERNAL_SERVER,i18n("No space left on device"));
+ break;
+ case NFSERR_ROFS:
+ error(ERR_COULD_NOT_WRITE,i18n("Read only file system"));
+ break;
+ case NFSERR_NAMETOOLONG:
+ error(ERR_INTERNAL_SERVER,i18n("Filename too long"));
+ break;
+ case NFSERR_NOTEMPTY:
+ error(ERR_COULD_NOT_RMDIR,text);
+ break;
+ //does this mapping make sense ?
+ case NFSERR_DQUOT:
+ error(ERR_INTERNAL_SERVER,i18n("Disk quota exceeded"));
+ break;
+ case NFSERR_STALE:
+ error(ERR_DOES_NOT_EXIST,text);
+ break;
+ default:
+ error(ERR_UNKNOWN,text);
+ break;
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void NFSProtocol::del( const KURL& url, bool isfile)
+{
+ QString thePath( QFile::encodeName(url.path()));
+ stripTrailingSlash(thePath);
+
+ QString fileName, parentDir;
+ getLastPart(thePath, fileName, parentDir);
+ stripTrailingSlash(parentDir);
+ kdDebug(7121)<<"del(): path: -"<<thePath<<"- file -"<<fileName<<"- parentDir: -"<<parentDir<<"-"<<endl;
+ if (isRoot(parentDir))
+ {
+ error(ERR_ACCESS_DENIED,thePath);
+ return;
+ }
+
+ NFSFileHandle fh=getFileHandle(parentDir);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,thePath);
+ return;
+ }
+
+ if (isfile)
+ {
+ kdDebug(7121)<<"Deleting file "<<thePath<<endl;
+ diropargs dirOpArgs;
+ memcpy(dirOpArgs.dir.data,fh,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(fileName);
+ dirOpArgs.name=tmpName.data();
+
+ nfsstat nfsStat;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_REMOVE,
+ (xdrproc_t) xdr_diropargs, (char*)&dirOpArgs,
+ (xdrproc_t) xdr_nfsstat, (char*)&nfsStat,total_timeout);
+ if (!checkForError(clnt_stat,nfsStat,thePath)) return;
+ kdDebug(7121)<<"removing "<<thePath<<" from cache"<<endl;
+ m_handleCache.remove(m_handleCache.find(thePath));
+ finished();
+ }
+ else
+ {
+ kdDebug(7121)<<"Deleting directory "<<thePath<<endl;
+ diropargs dirOpArgs;
+ memcpy(dirOpArgs.dir.data,fh,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(fileName);
+ dirOpArgs.name=tmpName.data();
+
+ nfsstat nfsStat;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_RMDIR,
+ (xdrproc_t) xdr_diropargs, (char*)&dirOpArgs,
+ (xdrproc_t) xdr_nfsstat, (char*)&nfsStat,total_timeout);
+ if (!checkForError(clnt_stat,nfsStat,thePath)) return;
+ kdDebug(7121)<<"removing "<<thePath<<" from cache"<<endl;
+ m_handleCache.remove(m_handleCache.find(thePath));
+ finished();
+ }
+}
+
+void NFSProtocol::chmod( const KURL& url, int permissions )
+{
+ QString thePath( QFile::encodeName(url.path()));
+ stripTrailingSlash(thePath);
+ kdDebug( 7121 ) << "chmod -"<< thePath << "-"<<endl;
+ if (isRoot(thePath) || isExportedDir(thePath))
+ {
+ error(ERR_ACCESS_DENIED,thePath);
+ return;
+ }
+
+ NFSFileHandle fh=getFileHandle(thePath);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,thePath);
+ return;
+ }
+
+ sattrargs sAttrArgs;
+ memcpy(sAttrArgs.file.data,fh,NFS_FHSIZE);
+ sAttrArgs.attributes.uid=(unsigned int)-1;
+ sAttrArgs.attributes.gid=(unsigned int)-1;
+ sAttrArgs.attributes.size=(unsigned int)-1;
+ sAttrArgs.attributes.atime.seconds=(unsigned int)-1;
+ sAttrArgs.attributes.atime.useconds=(unsigned int)-1;
+ sAttrArgs.attributes.mtime.seconds=(unsigned int)-1;
+ sAttrArgs.attributes.mtime.useconds=(unsigned int)-1;
+
+ sAttrArgs.attributes.mode=permissions;
+
+ nfsstat nfsStat;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_SETATTR,
+ (xdrproc_t) xdr_sattrargs, (char*)&sAttrArgs,
+ (xdrproc_t) xdr_nfsstat, (char*)&nfsStat,total_timeout);
+ if (!checkForError(clnt_stat,nfsStat,thePath)) return;
+
+ finished();
+}
+
+void NFSProtocol::get( const KURL& url )
+{
+ QString thePath( QFile::encodeName(url.path()));
+ kdDebug(7121)<<"get() -"<<thePath<<"-"<<endl;
+ NFSFileHandle fh=getFileHandle(thePath);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,thePath);
+ return;
+ }
+ readargs readArgs;
+ memcpy(readArgs.file.data,fh,NFS_FHSIZE);
+ readArgs.offset=0;
+ readArgs.count=NFS_MAXDATA;
+ readArgs.totalcount=NFS_MAXDATA;
+ readres readRes;
+ int offset(0);
+ char buf[NFS_MAXDATA];
+ readRes.readres_u.reply.data.data_val=buf;
+
+ QByteArray array;
+ do
+ {
+ int clnt_stat = clnt_call(m_client, NFSPROC_READ,
+ (xdrproc_t) xdr_readargs, (char*)&readArgs,
+ (xdrproc_t) xdr_readres, (char*)&readRes,total_timeout);
+ if (!checkForError(clnt_stat,readRes.status,thePath)) return;
+ if (readArgs.offset==0)
+ totalSize(readRes.readres_u.reply.attributes.size);
+
+ offset=readRes.readres_u.reply.data.data_len;
+ //kdDebug(7121)<<"read "<<offset<<" bytes"<<endl;
+ readArgs.offset+=offset;
+ if (offset>0)
+ {
+ array.setRawData(readRes.readres_u.reply.data.data_val, offset);
+ data( array );
+ array.resetRawData(readRes.readres_u.reply.data.data_val, offset);
+
+ processedSize(readArgs.offset);
+ }
+
+ } while (offset>0);
+ data( QByteArray() );
+ finished();
+}
+
+//TODO the partial putting thing is not yet implemented
+void NFSProtocol::put( const KURL& url, int _mode, bool _overwrite, bool /*_resume*/ )
+{
+ QString destPath( QFile::encodeName(url.path()));
+ kdDebug( 7121 ) << "Put -" << destPath <<"-"<<endl;
+ /*QString dest_part( dest_orig );
+ dest_part += ".part";*/
+
+ stripTrailingSlash(destPath);
+ QString parentDir, fileName;
+ getLastPart(destPath,fileName, parentDir);
+ if (isRoot(parentDir))
+ {
+ error(ERR_WRITE_ACCESS_DENIED,destPath);
+ return;
+ }
+
+ NFSFileHandle destFH;
+ destFH=getFileHandle(destPath);
+ kdDebug(7121)<<"file handle for -"<<destPath<<"- is "<<destFH<<endl;
+
+ //the file exists and we don't want to overwrite
+ if ((!_overwrite) && (!destFH.isInvalid()))
+ {
+ error(ERR_FILE_ALREADY_EXIST,destPath);
+ return;
+ }
+ //TODO: is this correct ?
+ //we have to "create" the file anyway, no matter if it already
+ //exists or not
+ //if we don't create it new, written text will be, hmm, "inserted"
+ //in the existing file, i.e. a file could not become smaller, since
+ //write only overwrites or extends, but doesn't remove stuff from a file (aleXXX)
+
+ kdDebug(7121)<<"creating the file -"<<fileName<<"-"<<endl;
+ NFSFileHandle parentFH;
+ parentFH=getFileHandle(parentDir);
+ //cerr<<"fh for parent dir: "<<parentFH<<endl;
+ //the directory doesn't exist
+ if (parentFH.isInvalid())
+ {
+ kdDebug(7121)<<"parent directory -"<<parentDir<<"- does not exist"<<endl;
+ error(ERR_DOES_NOT_EXIST,parentDir);
+ return;
+ }
+ createargs createArgs;
+ memcpy(createArgs.where.dir.data,(const char*)parentFH,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(fileName);
+ createArgs.where.name=tmpName.data();
+
+ //the mode is apparently ignored if the file already exists
+ if (_mode==-1) createArgs.attributes.mode=0644;
+ else createArgs.attributes.mode=_mode;
+ createArgs.attributes.uid=geteuid();
+ createArgs.attributes.gid=getegid();
+ //this is required, otherwise we are not able to write shorter files
+ createArgs.attributes.size=0;
+ //hmm, do we need something here ? I don't think so
+ createArgs.attributes.atime.seconds=(unsigned int)-1;
+ createArgs.attributes.atime.useconds=(unsigned int)-1;
+ createArgs.attributes.mtime.seconds=(unsigned int)-1;
+ createArgs.attributes.mtime.useconds=(unsigned int)-1;
+
+ diropres dirOpRes;
+ int clnt_stat = clnt_call(m_client, NFSPROC_CREATE,
+ (xdrproc_t) xdr_createargs, (char*)&createArgs,
+ (xdrproc_t) xdr_diropres, (char*)&dirOpRes,total_timeout);
+ if (!checkForError(clnt_stat,dirOpRes.status,fileName)) return;
+ //we created the file successfully
+ //destFH=getFileHandle(destPath);
+ destFH=dirOpRes.diropres_u.diropres.file.data;
+ kdDebug(7121)<<"file -"<<fileName<<"- in dir -"<<parentDir<<"- created successfully"<<endl;
+ //cerr<<"with fh "<<destFH<<endl;
+
+ //now we can put
+ int result;
+ // Loop until we got 0 (end of data)
+ writeargs writeArgs;
+ memcpy(writeArgs.file.data,(const char*)destFH,NFS_FHSIZE);
+ writeArgs.beginoffset=0;
+ writeArgs.totalcount=0;
+ writeArgs.offset=0;
+ attrstat attrStat;
+ int bytesWritten(0);
+ kdDebug(7121)<<"starting to put"<<endl;
+ do
+ {
+ QByteArray buffer;
+ dataReq(); // Request for data
+ result = readData( buffer );
+ //kdDebug(7121)<<"received "<<result<<" bytes for putting"<<endl;
+ char * data=buffer.data();
+ int bytesToWrite=buffer.size();
+ int writeNow(0);
+ if (result > 0)
+ {
+ do
+ {
+ if (bytesToWrite>NFS_MAXDATA)
+ {
+ writeNow=NFS_MAXDATA;
+ }
+ else
+ {
+ writeNow=bytesToWrite;
+ };
+ writeArgs.data.data_val=data;
+ writeArgs.data.data_len=writeNow;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_WRITE,
+ (xdrproc_t) xdr_writeargs, (char*)&writeArgs,
+ (xdrproc_t) xdr_attrstat, (char*)&attrStat,total_timeout);
+ //kdDebug(7121)<<"written"<<endl;
+ if (!checkForError(clnt_stat,attrStat.status,fileName)) return;
+ bytesWritten+=writeNow;
+ writeArgs.offset=bytesWritten;
+
+ //adjust the pointer
+ data=data+writeNow;
+ //decrease the rest
+ bytesToWrite-=writeNow;
+ } while (bytesToWrite>0);
+ }
+ } while ( result > 0 );
+ finished();
+}
+
+void NFSProtocol::rename( const KURL &src, const KURL &dest, bool _overwrite )
+{
+ QString srcPath( QFile::encodeName(src.path()));
+ QString destPath( QFile::encodeName(dest.path()));
+ stripTrailingSlash(srcPath);
+ stripTrailingSlash(destPath);
+ kdDebug(7121)<<"renaming -"<<srcPath<<"- to -"<<destPath<<"-"<<endl;
+
+ if (isRoot(srcPath) || isExportedDir(srcPath))
+ {
+ error(ERR_CANNOT_RENAME,srcPath);
+ return;
+ }
+
+ if (!_overwrite)
+ {
+ NFSFileHandle testFH;
+ testFH=getFileHandle(destPath);
+ if (!testFH.isInvalid())
+ {
+ error(ERR_FILE_ALREADY_EXIST,destPath);
+ return;
+ }
+ }
+
+ QString srcFileName, srcParentDir, destFileName, destParentDir;
+
+ getLastPart(srcPath, srcFileName, srcParentDir);
+ NFSFileHandle srcFH=getFileHandle(srcParentDir);
+ if (srcFH.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,srcParentDir);
+ return;
+ }
+ renameargs renameArgs;
+ memcpy(renameArgs.from.dir.data,srcFH,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(srcFileName);
+ renameArgs.from.name=tmpName.data();
+
+ getLastPart(destPath, destFileName, destParentDir);
+ NFSFileHandle destFH=getFileHandle(destParentDir);
+ if (destFH.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,destParentDir);
+ return;
+ }
+ memcpy(renameArgs.to.dir.data,destFH,NFS_FHSIZE);
+ QCString tmpName2=QFile::encodeName(destFileName);
+ renameArgs.to.name=tmpName2.data();
+ nfsstat nfsStat;
+
+ int clnt_stat = clnt_call(m_client, NFSPROC_RENAME,
+ (xdrproc_t) xdr_renameargs, (char*)&renameArgs,
+ (xdrproc_t) xdr_nfsstat, (char*)&nfsStat,total_timeout);
+ if (!checkForError(clnt_stat,nfsStat,destPath)) return;
+ finished();
+}
+
+void NFSProtocol::copy( const KURL &src, const KURL &dest, int _mode, bool _overwrite )
+{
+ //prepare the source
+ QString thePath( QFile::encodeName(src.path()));
+ stripTrailingSlash(thePath);
+ kdDebug( 7121 ) << "Copy to -" << thePath <<"-"<<endl;
+ NFSFileHandle fh=getFileHandle(thePath);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,thePath);
+ return;
+ };
+
+ //create the destination
+ QString destPath( QFile::encodeName(dest.path()));
+ stripTrailingSlash(destPath);
+ QString parentDir, fileName;
+ getLastPart(destPath,fileName, parentDir);
+ if (isRoot(parentDir))
+ {
+ error(ERR_ACCESS_DENIED,destPath);
+ return;
+ }
+ NFSFileHandle destFH;
+ destFH=getFileHandle(destPath);
+ kdDebug(7121)<<"file handle for -"<<destPath<<"- is "<<destFH<<endl;
+
+ //the file exists and we don't want to overwrite
+ if ((!_overwrite) && (!destFH.isInvalid()))
+ {
+ error(ERR_FILE_ALREADY_EXIST,destPath);
+ return;
+ }
+ //TODO: is this correct ?
+ //we have to "create" the file anyway, no matter if it already
+ //exists or not
+ //if we don't create it new, written text will be, hmm, "inserted"
+ //in the existing file, i.e. a file could not become smaller, since
+ //write only overwrites or extends, but doesn't remove stuff from a file
+
+ kdDebug(7121)<<"creating the file -"<<fileName<<"-"<<endl;
+ NFSFileHandle parentFH;
+ parentFH=getFileHandle(parentDir);
+ //the directory doesn't exist
+ if (parentFH.isInvalid())
+ {
+ kdDebug(7121)<<"parent directory -"<<parentDir<<"- does not exist"<<endl;
+ error(ERR_DOES_NOT_EXIST,parentDir);
+ return;
+ };
+ createargs createArgs;
+ memcpy(createArgs.where.dir.data,(const char*)parentFH,NFS_FHSIZE);
+ QCString tmpName=QFile::encodeName(fileName);
+ createArgs.where.name=tmpName.data();
+ if (_mode==-1) createArgs.attributes.mode=0644;
+ else createArgs.attributes.mode=_mode;
+ createArgs.attributes.uid=geteuid();
+ createArgs.attributes.gid=getegid();
+ createArgs.attributes.size=0;
+ createArgs.attributes.atime.seconds=(unsigned int)-1;
+ createArgs.attributes.atime.useconds=(unsigned int)-1;
+ createArgs.attributes.mtime.seconds=(unsigned int)-1;
+ createArgs.attributes.mtime.useconds=(unsigned int)-1;
+
+ diropres dirOpRes;
+ int clnt_stat = clnt_call(m_client, NFSPROC_CREATE,
+ (xdrproc_t) xdr_createargs, (char*)&createArgs,
+ (xdrproc_t) xdr_diropres, (char*)&dirOpRes,total_timeout);
+ if (!checkForError(clnt_stat,dirOpRes.status,destPath)) return;
+ //we created the file successfully
+ destFH=dirOpRes.diropres_u.diropres.file.data;
+ kdDebug(7121)<<"file -"<<fileName<<"- in dir -"<<parentDir<<"- created successfully"<<endl;
+
+ char buf[NFS_MAXDATA];
+ writeargs writeArgs;
+ memcpy(writeArgs.file.data,(const char*)destFH,NFS_FHSIZE);
+ writeArgs.beginoffset=0;
+ writeArgs.totalcount=0;
+ writeArgs.offset=0;
+ writeArgs.data.data_val=buf;
+ attrstat attrStat;
+
+ readargs readArgs;
+ memcpy(readArgs.file.data,fh,NFS_FHSIZE);
+ readArgs.offset=0;
+ readArgs.count=NFS_MAXDATA;
+ readArgs.totalcount=NFS_MAXDATA;
+ readres readRes;
+ readRes.readres_u.reply.data.data_val=buf;
+
+ int bytesRead(0);
+ do
+ {
+ //first read
+ int clnt_stat = clnt_call(m_client, NFSPROC_READ,
+ (xdrproc_t) xdr_readargs, (char*)&readArgs,
+ (xdrproc_t) xdr_readres, (char*)&readRes,total_timeout);
+ if (!checkForError(clnt_stat,readRes.status,thePath)) return;
+ if (readArgs.offset==0)
+ totalSize(readRes.readres_u.reply.attributes.size);
+
+ bytesRead=readRes.readres_u.reply.data.data_len;
+ //kdDebug(7121)<<"read "<<bytesRead<<" bytes"<<endl;
+ //then write
+ if (bytesRead>0)
+ {
+ readArgs.offset+=bytesRead;
+
+ writeArgs.data.data_len=bytesRead;
+
+ clnt_stat = clnt_call(m_client, NFSPROC_WRITE,
+ (xdrproc_t) xdr_writeargs, (char*)&writeArgs,
+ (xdrproc_t) xdr_attrstat, (char*)&attrStat,total_timeout);
+ //kdDebug(7121)<<"written"<<endl;
+ if (!checkForError(clnt_stat,attrStat.status,destPath)) return;
+ writeArgs.offset+=bytesRead;
+ }
+ } while (bytesRead>0);
+
+ finished();
+}
+
+//TODO why isn't this even called ?
+void NFSProtocol::symlink( const QString &target, const KURL &dest, bool )
+{
+ kdDebug(7121)<<"symlinking "<<endl;
+ QString destPath=dest.path();
+ stripTrailingSlash(destPath);
+
+ QString parentDir, fileName;
+ getLastPart(destPath,fileName, parentDir);
+ kdDebug(7121)<<"symlinking "<<parentDir<<" "<<fileName<<" to "<<target<<endl;
+ NFSFileHandle fh=getFileHandle(parentDir);
+ if (fh.isInvalid())
+ {
+ error(ERR_DOES_NOT_EXIST,parentDir);
+ return;
+ }
+ if (isRoot(parentDir))
+ {
+ error(ERR_ACCESS_DENIED,destPath);
+ return;
+ }
+
+ kdDebug(7121)<<"tach"<<endl;
+ QCString tmpStr=target.latin1();
+ symlinkargs symLinkArgs;
+ symLinkArgs.to=tmpStr.data();
+ memcpy(symLinkArgs.from.dir.data,(const char*)fh,NFS_FHSIZE);
+ QCString tmpStr2=QFile::encodeName(destPath);
+ symLinkArgs.from.name=tmpStr2.data();
+
+ nfsstat nfsStat;
+ int clnt_stat = clnt_call(m_client, NFSPROC_SYMLINK,
+ (xdrproc_t) xdr_symlinkargs, (char*)&symLinkArgs,
+ (xdrproc_t) xdr_nfsstat, (char*)&nfsStat,total_timeout);
+ if (!checkForError(clnt_stat,nfsStat,destPath)) return;
+
+ finished();
+
+}
+
+bool NFSProtocol::isValidLink(const QString& parentDir, const QString& linkDest)
+{
+ kdDebug(7121)<<"isValidLink: parent: "<<parentDir<<" link: "<<linkDest<<endl;
+ if (linkDest.isEmpty()) return FALSE;
+ if (isAbsoluteLink(linkDest))
+ {
+ kdDebug(7121)<<"is an absolute link"<<endl;
+ return QFile::exists(linkDest);
+ }
+ else
+ {
+ kdDebug(7121)<<"is a relative link"<<endl;
+ QString absDest=parentDir+"/"+linkDest;
+ kdDebug(7121)<<"pointing abs to "<<absDest<<endl;
+ absDest=removeFirstPart(absDest);
+ kdDebug(7121)<<"removed first part "<<absDest<<endl;
+ absDest=QDir::cleanDirPath(absDest);
+ kdDebug(7121)<<"simplified to "<<absDest<<endl;
+ if (absDest.find("../")==0)
+ return FALSE;
+
+ kdDebug(7121)<<"is inside the nfs tree"<<endl;
+ absDest=parentDir+"/"+linkDest;
+ absDest=QDir::cleanDirPath(absDest);
+ kdDebug(7121)<<"getting file handle of "<<absDest<<endl;
+ NFSFileHandle fh=getFileHandle(absDest);
+ return (!fh.isInvalid());
+ }
+ return FALSE;
+}
+
diff --git a/kioslave/nfs/kio_nfs.h b/kioslave/nfs/kio_nfs.h
new file mode 100644
index 000000000..23eb0b467
--- /dev/null
+++ b/kioslave/nfs/kio_nfs.h
@@ -0,0 +1,109 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KIO_NFS_H
+#define KIO_NFS_H
+
+#include <kio/slavebase.h>
+#include <kio/global.h>
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qintdict.h>
+#include <qtimer.h>
+
+#define PORTMAP //this seems to be required to compile on Solaris
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+class NFSFileHandle
+{
+ public:
+ NFSFileHandle();
+ NFSFileHandle(const NFSFileHandle & handle);
+ ~NFSFileHandle();
+ NFSFileHandle& operator= (const NFSFileHandle& src);
+ NFSFileHandle& operator= (const char* src);
+ operator const char* () const {return m_handle;}
+ bool isInvalid() const {return m_isInvalid;}
+ void setInvalid() {m_isInvalid=TRUE;}
+// time_t age() const;
+ protected:
+ char m_handle[NFS_FHSIZE+1];
+ bool m_isInvalid;
+// time_t m_detectTime;
+};
+
+//ostream& operator<<(ostream&, const NFSFileHandle&);
+
+typedef QMap<QString,NFSFileHandle> NFSFileHandleMap;
+
+
+class NFSProtocol : public KIO::SlaveBase
+{
+ public:
+ NFSProtocol (const QCString &pool, const QCString &app );
+ virtual ~NFSProtocol();
+
+ virtual void openConnection();
+ virtual void closeConnection();
+
+ virtual void setHost( const QString& host, int port, const QString& user, const QString& pass );
+
+ virtual void put( const KURL& url, int _mode,bool _overwrite, bool _resume );
+ virtual void get( const KURL& url );
+ virtual void listDir( const KURL& url);
+ virtual void symlink( const QString &target, const KURL &dest, bool );
+ virtual void stat( const KURL & url);
+ virtual void mkdir( const KURL& url, int permissions );
+ virtual void del( const KURL& url, bool isfile);
+ 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 );
+ protected:
+// void createVirtualDirEntry(KIO::UDSEntry & entry);
+ bool checkForError(int clientStat, int nfsStat, const QString& text);
+ bool isExportedDir(const QString& path);
+ void completeUDSEntry(KIO::UDSEntry& entry, fattr& attributes);
+ void completeBadLinkUDSEntry(KIO::UDSEntry& entry, fattr& attributes);
+ void completeAbsoluteLinkUDSEntry(KIO::UDSEntry& entry, const QCString& path);
+ bool isValidLink(const QString& parentDir, const QString& linkDest);
+// bool isAbsoluteLink(const QString& path);
+
+ NFSFileHandle getFileHandle(QString path);
+
+ NFSFileHandleMap m_handleCache;
+ QIntDict<QString> m_usercache; // maps long ==> QString *
+ QIntDict<QString> m_groupcache;
+
+ QStringList m_exportedDirs;
+ QString m_currentHost;
+ CLIENT *m_client;
+ CLIENT *m_nfsClient;
+ timeval total_timeout;
+ timeval pertry_timeout;
+ int m_sock;
+ time_t m_lastCheck;
+ void checkForOldFHs();
+};
+
+#endif
diff --git a/kioslave/nfs/mount.h b/kioslave/nfs/mount.h
new file mode 100644
index 000000000..c3b8c217f
--- /dev/null
+++ b/kioslave/nfs/mount.h
@@ -0,0 +1,325 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _MOUNT_H_RPCGEN
+#define _MOUNT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+#ifndef _rpcsvc_mount_h
+#define _rpcsvc_mount_h
+#define MNTPATHLEN 1024
+#define MNTNAMLEN 255
+#define FHSIZE 32
+
+typedef char fhandle[FHSIZE];
+#ifdef __cplusplus
+extern "C" bool_t xdr_fhandle(XDR *, fhandle);
+#elif __STDC__
+extern bool_t xdr_fhandle(XDR *, fhandle);
+#else /* Old Style C */
+bool_t xdr_fhandle();
+#endif /* Old Style C */
+
+
+struct fhstatus {
+ u_int fhs_status;
+ union {
+ fhandle fhs_fhandle;
+ } fhstatus_u;
+};
+typedef struct fhstatus fhstatus;
+#ifdef __cplusplus
+extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*);
+#elif __STDC__
+extern bool_t xdr_fhstatus(XDR *, fhstatus*);
+#else /* Old Style C */
+bool_t xdr_fhstatus();
+#endif /* Old Style C */
+
+
+typedef char *dirpath;
+#ifdef __cplusplus
+extern "C" bool_t xdr_dirpath(XDR *, dirpath*);
+#elif __STDC__
+extern bool_t xdr_dirpath(XDR *, dirpath*);
+#else /* Old Style C */
+bool_t xdr_dirpath();
+#endif /* Old Style C */
+
+
+typedef char *name;
+#ifdef __cplusplus
+extern "C" bool_t xdr_name(XDR *, name*);
+#elif __STDC__
+extern bool_t xdr_name(XDR *, name*);
+#else /* Old Style C */
+bool_t xdr_name();
+#endif /* Old Style C */
+
+
+typedef struct mountbody *mountlist;
+#ifdef __cplusplus
+extern "C" bool_t xdr_mountlist(XDR *, mountlist*);
+#elif __STDC__
+extern bool_t xdr_mountlist(XDR *, mountlist*);
+#else /* Old Style C */
+bool_t xdr_mountlist();
+#endif /* Old Style C */
+
+
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+typedef struct mountbody mountbody;
+#ifdef __cplusplus
+extern "C" bool_t xdr_mountbody(XDR *, mountbody*);
+#elif __STDC__
+extern bool_t xdr_mountbody(XDR *, mountbody*);
+#else /* Old Style C */
+bool_t xdr_mountbody();
+#endif /* Old Style C */
+
+
+typedef struct groupnode *groups;
+#ifdef __cplusplus
+extern "C" bool_t xdr_groups(XDR *, groups*);
+#elif __STDC__
+extern bool_t xdr_groups(XDR *, groups*);
+#else /* Old Style C */
+bool_t xdr_groups();
+#endif /* Old Style C */
+
+
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+typedef struct groupnode groupnode;
+#ifdef __cplusplus
+extern "C" bool_t xdr_groupnode(XDR *, groupnode*);
+#elif __STDC__
+extern bool_t xdr_groupnode(XDR *, groupnode*);
+#else /* Old Style C */
+bool_t xdr_groupnode();
+#endif /* Old Style C */
+
+
+typedef struct exportnode *exports;
+#ifdef __cplusplus
+extern "C" bool_t xdr_exports(XDR *, exports*);
+#elif __STDC__
+extern bool_t xdr_exports(XDR *, exports*);
+#else /* Old Style C */
+bool_t xdr_exports();
+#endif /* Old Style C */
+
+
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+typedef struct exportnode exportnode;
+#ifdef __cplusplus
+extern "C" bool_t xdr_exportnode(XDR *, exportnode*);
+#elif __STDC__
+extern bool_t xdr_exportnode(XDR *, exportnode*);
+#else /* Old Style C */
+bool_t xdr_exportnode();
+#endif /* Old Style C */
+
+
+struct ppathcnf {
+ int pc_link_max;
+ short pc_max_canon;
+ short pc_max_input;
+ short pc_name_max;
+ short pc_path_max;
+ short pc_pipe_buf;
+ u_char pc_vdisable;
+ char pc_xxx;
+ short pc_mask[2];
+};
+typedef struct ppathcnf ppathcnf;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#elif __STDC__
+extern bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#else /* Old Style C */
+bool_t xdr_ppathcnf();
+#endif /* Old Style C */
+
+#endif /*!_rpcsvc_mount_h*/
+
+#define MOUNTPROG ((u_long)100005)
+#define MOUNTVERS ((u_long)1)
+
+#ifdef __cplusplus
+#define MOUNTPROC_NULL ((u_long)0)
+extern "C" void * mountproc_null_1(void *, CLIENT *);
+extern "C" void * mountproc_null_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_MNT ((u_long)1)
+extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
+extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_DUMP ((u_long)2)
+extern "C" mountlist * mountproc_dump_1(void *, CLIENT *);
+extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_UMNT ((u_long)3)
+extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *);
+extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_UMNTALL ((u_long)4)
+extern "C" void * mountproc_umntall_1(void *, CLIENT *);
+extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORT ((u_long)5)
+extern "C" exports * mountproc_export_1(void *, CLIENT *);
+extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORTALL ((u_long)6)
+extern "C" exports * mountproc_exportall_1(void *, CLIENT *);
+extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *);
+
+#elif __STDC__
+#define MOUNTPROC_NULL ((u_long)0)
+extern void * mountproc_null_1(void *, CLIENT *);
+extern void * mountproc_null_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_MNT ((u_long)1)
+extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
+extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_DUMP ((u_long)2)
+extern mountlist * mountproc_dump_1(void *, CLIENT *);
+extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_UMNT ((u_long)3)
+extern void * mountproc_umnt_1(dirpath *, CLIENT *);
+extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
+#define MOUNTPROC_UMNTALL ((u_long)4)
+extern void * mountproc_umntall_1(void *, CLIENT *);
+extern void * mountproc_umntall_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORT ((u_long)5)
+extern exports * mountproc_export_1(void *, CLIENT *);
+extern exports * mountproc_export_1_svc(void *, struct svc_req *);
+#define MOUNTPROC_EXPORTALL ((u_long)6)
+extern exports * mountproc_exportall_1(void *, CLIENT *);
+extern exports * mountproc_exportall_1_svc(void *, struct svc_req *);
+
+#else /* Old Style C */
+#define MOUNTPROC_NULL ((u_long)0)
+extern void * mountproc_null_1();
+extern void * mountproc_null_1_svc();
+#define MOUNTPROC_MNT ((u_long)1)
+extern fhstatus * mountproc_mnt_1();
+extern fhstatus * mountproc_mnt_1_svc();
+#define MOUNTPROC_DUMP ((u_long)2)
+extern mountlist * mountproc_dump_1();
+extern mountlist * mountproc_dump_1_svc();
+#define MOUNTPROC_UMNT ((u_long)3)
+extern void * mountproc_umnt_1();
+extern void * mountproc_umnt_1_svc();
+#define MOUNTPROC_UMNTALL ((u_long)4)
+extern void * mountproc_umntall_1();
+extern void * mountproc_umntall_1_svc();
+#define MOUNTPROC_EXPORT ((u_long)5)
+extern exports * mountproc_export_1();
+extern exports * mountproc_export_1_svc();
+#define MOUNTPROC_EXPORTALL ((u_long)6)
+extern exports * mountproc_exportall_1();
+extern exports * mountproc_exportall_1_svc();
+#endif /* Old Style C */
+#define MOUNTVERS_POSIX ((u_long)2)
+
+#ifdef __cplusplus
+extern "C" void * mountproc_null_2(void *, CLIENT *);
+extern "C" void * mountproc_null_2_svc(void *, struct svc_req *);
+extern "C" fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern "C" fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern "C" mountlist * mountproc_dump_2(void *, CLIENT *);
+extern "C" mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern "C" void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern "C" void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern "C" void * mountproc_umntall_2(void *, CLIENT *);
+extern "C" void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_export_2(void *, CLIENT *);
+extern "C" exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_exportall_2(void *, CLIENT *);
+extern "C" exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern "C" ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern "C" ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#elif __STDC__
+extern void * mountproc_null_2(void *, CLIENT *);
+extern void * mountproc_null_2_svc(void *, struct svc_req *);
+extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern mountlist * mountproc_dump_2(void *, CLIENT *);
+extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern void * mountproc_umntall_2(void *, CLIENT *);
+extern void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern exports * mountproc_export_2(void *, CLIENT *);
+extern exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern exports * mountproc_exportall_2(void *, CLIENT *);
+extern exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#else /* Old Style C */
+extern void * mountproc_null_2();
+extern void * mountproc_null_2_svc();
+extern fhstatus * mountproc_mnt_2();
+extern fhstatus * mountproc_mnt_2_svc();
+extern mountlist * mountproc_dump_2();
+extern mountlist * mountproc_dump_2_svc();
+extern void * mountproc_umnt_2();
+extern void * mountproc_umnt_2_svc();
+extern void * mountproc_umntall_2();
+extern void * mountproc_umntall_2_svc();
+extern exports * mountproc_export_2();
+extern exports * mountproc_export_2_svc();
+extern exports * mountproc_exportall_2();
+extern exports * mountproc_exportall_2_svc();
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2();
+extern ppathcnf * mountproc_pathconf_2_svc();
+#endif /* Old Style C */
+
+#endif /* !_MOUNT_H_RPCGEN */
diff --git a/kioslave/nfs/mount.x b/kioslave/nfs/mount.x
new file mode 100644
index 000000000..4aaf97de9
--- /dev/null
+++ b/kioslave/nfs/mount.x
@@ -0,0 +1,255 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+#endif
+
+const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255; /* maximum bytes in a name argument */
+const FHSIZE = 32; /* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];
+
+/*
+ * If a status of zero is returned, the call completed successfully, and
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+ fhandle fhs_fhandle;
+default:
+ void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+ int pc_link_max; /* max links allowed */
+ short pc_max_canon; /* max line len for a tty */
+ short pc_max_input; /* input a tty can eat all at once */
+ short pc_name_max; /* max file name length (dir entry) */
+ short pc_path_max; /* max path name length (/x/y/x/.. ) */
+ short pc_pipe_buf; /* size of a pipe (bytes) */
+ u_char pc_vdisable; /* safe char to turn off c_cc[i] */
+ char pc_xxx; /* alignment padding; cc_t == char */
+ short pc_mask[2]; /* validity and boolean bits */
+};
+
+program MOUNTPROG {
+ /*
+ * Version one of the mount protocol communicates with version two
+ * of the NFS protocol. The only connecting point is the fhandle
+ * structure, which is the same for both protocols.
+ */
+ version MOUNTVERS {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+ } = 1;
+
+ /*
+ * Version two of the mount protocol communicates with version two
+ * of the NFS protocol.
+ * The only difference from version one is the addition of a POSIX
+ * pathconf call.
+ */
+ version MOUNTVERS_POSIX {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+
+ /*
+ * POSIX pathconf info (Sun hack)
+ */
+ ppathcnf
+ MOUNTPROC_PATHCONF(dirpath) = 7;
+ } = 2;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/kioslave/nfs/mount_xdr.c b/kioslave/nfs/mount_xdr.c
new file mode 100644
index 000000000..38a43ca28
--- /dev/null
+++ b/kioslave/nfs/mount_xdr.c
@@ -0,0 +1,335 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <arpa/inet.h>
+
+#include "mount.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+bool_t
+xdr_fhandle(XDR *xdrs, fhandle objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_opaque(xdrs, objp, FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_fhstatus(XDR *xdrs, fhstatus *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_u_int(xdrs, &objp->fhs_status)) {
+ return (FALSE);
+ }
+ switch (objp->fhs_status) {
+ case 0:
+ if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_dirpath(XDR *xdrs, dirpath *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_name(XDR *xdrs, name *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountlist(XDR *xdrs, mountlist *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountbody(XDR *xdrs, mountbody *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_name(xdrs, &objp->ml_hostname)) {
+ return (FALSE);
+ }
+ if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_mountlist(xdrs, &objp->ml_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groups(XDR *xdrs, groups *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groupnode(XDR *xdrs, groupnode *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_name(xdrs, &objp->gr_name)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->gr_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exports(XDR *xdrs, exports *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exportnode(XDR *xdrs, exportnode *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->ex_groups)) {
+ return (FALSE);
+ }
+ if (!xdr_exports(xdrs, &objp->ex_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ppathcnf(XDR *xdrs, ppathcnf *objp)
+{
+
+ register int32_t *buf=buf;
+
+ int i=i;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_U_INT32(buf,objp->pc_link_max);
+ IXDR_PUT_SHORT(buf,objp->pc_max_canon);
+ IXDR_PUT_SHORT(buf,objp->pc_max_input);
+ IXDR_PUT_SHORT(buf,objp->pc_name_max);
+ IXDR_PUT_SHORT(buf,objp->pc_path_max);
+ IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ IXDR_PUT_SHORT(buf,*genp++);
+ }
+ };
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->pc_link_max = IXDR_GET_U_INT32(buf);
+ objp->pc_max_canon = IXDR_GET_SHORT(buf);
+ objp->pc_max_input = IXDR_GET_SHORT(buf);
+ objp->pc_name_max = IXDR_GET_SHORT(buf);
+ objp->pc_path_max = IXDR_GET_SHORT(buf);
+ objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ *genp++ = IXDR_GET_SHORT(buf);
+ }
+ };
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/kioslave/nfs/nfs.protocol b/kioslave/nfs/nfs.protocol
new file mode 100644
index 000000000..377b01505
--- /dev/null
+++ b/kioslave/nfs/nfs.protocol
@@ -0,0 +1,14 @@
+[Protocol]
+exec=kio_nfs
+protocol=nfs
+input=none
+output=filesystem
+listing=Name,Type,Size,Date,AccessDate,CreationDate,Access,Owner,Group,Link
+reading=true
+writing=true
+makedir=true
+deleting=true
+linking=true
+moving=true
+DocPath=kioslave/nfs.html
+Icon=nfs_mount
diff --git a/kioslave/nfs/nfs_prot.h b/kioslave/nfs/nfs_prot.h
new file mode 100644
index 000000000..5ed218f20
--- /dev/null
+++ b/kioslave/nfs/nfs_prot.h
@@ -0,0 +1,699 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NFS_PROT_H_RPCGEN
+#define _NFS_PROT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1987, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)nfs_prot.x 1.3 91/03/11 TIRPC 1.0 */
+#ifndef _rpcsvc_nfs_prot_h
+#define _rpcsvc_nfs_prot_h
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV -1
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+enum nfsstat {
+ NFS_OK = 0,
+ NFSERR_PERM = 1,
+ NFSERR_NOENT = 2,
+ NFSERR_IO = 5,
+ NFSERR_NXIO = 6,
+ NFSERR_ACCES = 13,
+ NFSERR_EXIST = 17,
+ NFSERR_NODEV = 19,
+ NFSERR_NOTDIR = 20,
+ NFSERR_ISDIR = 21,
+ NFSERR_INVAL = 22,
+ NFSERR_FBIG = 27,
+ NFSERR_NOSPC = 28,
+ NFSERR_ROFS = 30,
+ NFSERR_NAMETOOLONG = 63,
+ NFSERR_NOTEMPTY = 66,
+ NFSERR_DQUOT = 69,
+ NFSERR_STALE = 70,
+ NFSERR_WFLUSH = 99
+};
+typedef enum nfsstat nfsstat;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfsstat(XDR *, nfsstat*);
+#elif __STDC__
+extern bool_t xdr_nfsstat(XDR *, nfsstat*);
+#else /* Old Style C */
+bool_t xdr_nfsstat();
+#endif /* Old Style C */
+
+
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5,
+ NFSOCK = 6,
+ NFBAD = 7,
+ NFFIFO = 8
+};
+typedef enum ftype ftype;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ftype(XDR *, ftype*);
+#elif __STDC__
+extern bool_t xdr_ftype(XDR *, ftype*);
+#else /* Old Style C */
+bool_t xdr_ftype();
+#endif /* Old Style C */
+
+
+struct nfs_fh {
+ char data[NFS_FHSIZE];
+};
+typedef struct nfs_fh nfs_fh;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#elif __STDC__
+extern bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#else /* Old Style C */
+bool_t xdr_nfs_fh();
+#endif /* Old Style C */
+
+
+struct nfstime {
+ u_int seconds;
+ u_int useconds;
+};
+typedef struct nfstime nfstime;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfstime(XDR *, nfstime*);
+#elif __STDC__
+extern bool_t xdr_nfstime(XDR *, nfstime*);
+#else /* Old Style C */
+bool_t xdr_nfstime();
+#endif /* Old Style C */
+
+
+struct fattr {
+ ftype type;
+ u_int mode;
+ u_int nlink;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ u_int blocksize;
+ u_int rdev;
+ u_int blocks;
+ u_int fsid;
+ u_int fileid;
+ nfstime atime;
+ nfstime mtime;
+ nfstime ctime;
+};
+typedef struct fattr fattr;
+#ifdef __cplusplus
+extern "C" bool_t xdr_fattr(XDR *, fattr*);
+#elif __STDC__
+extern bool_t xdr_fattr(XDR *, fattr*);
+#else /* Old Style C */
+bool_t xdr_fattr();
+#endif /* Old Style C */
+
+
+struct sattr {
+ u_int mode;
+ u_int uid;
+ u_int gid;
+ u_int size;
+ nfstime atime;
+ nfstime mtime;
+};
+typedef struct sattr sattr;
+#ifdef __cplusplus
+extern "C" bool_t xdr_sattr(XDR *, sattr*);
+#elif __STDC__
+extern bool_t xdr_sattr(XDR *, sattr*);
+#else /* Old Style C */
+bool_t xdr_sattr();
+#endif /* Old Style C */
+
+
+typedef char *filename;
+#ifdef __cplusplus
+extern "C" bool_t xdr_filename(XDR *, filename*);
+#elif __STDC__
+extern bool_t xdr_filename(XDR *, filename*);
+#else /* Old Style C */
+bool_t xdr_filename();
+#endif /* Old Style C */
+
+
+typedef char *nfspath;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfspath(XDR *, nfspath*);
+#elif __STDC__
+extern bool_t xdr_nfspath(XDR *, nfspath*);
+#else /* Old Style C */
+bool_t xdr_nfspath();
+#endif /* Old Style C */
+
+
+struct attrstat {
+ nfsstat status;
+ union {
+ fattr attributes;
+ } attrstat_u;
+};
+typedef struct attrstat attrstat;
+#ifdef __cplusplus
+extern "C" bool_t xdr_attrstat(XDR *, attrstat*);
+#elif __STDC__
+extern bool_t xdr_attrstat(XDR *, attrstat*);
+#else /* Old Style C */
+bool_t xdr_attrstat();
+#endif /* Old Style C */
+
+
+struct sattrargs {
+ nfs_fh file;
+ sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_sattrargs(XDR *, sattrargs*);
+#elif __STDC__
+extern bool_t xdr_sattrargs(XDR *, sattrargs*);
+#else /* Old Style C */
+bool_t xdr_sattrargs();
+#endif /* Old Style C */
+
+
+struct diropargs {
+ nfs_fh dir;
+ filename name;
+};
+typedef struct diropargs diropargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropargs(XDR *, diropargs*);
+#elif __STDC__
+extern bool_t xdr_diropargs(XDR *, diropargs*);
+#else /* Old Style C */
+bool_t xdr_diropargs();
+#endif /* Old Style C */
+
+
+struct diropokres {
+ nfs_fh file;
+ fattr attributes;
+};
+typedef struct diropokres diropokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropokres(XDR *, diropokres*);
+#elif __STDC__
+extern bool_t xdr_diropokres(XDR *, diropokres*);
+#else /* Old Style C */
+bool_t xdr_diropokres();
+#endif /* Old Style C */
+
+
+struct diropres {
+ nfsstat status;
+ union {
+ diropokres diropres;
+ } diropres_u;
+};
+typedef struct diropres diropres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_diropres(XDR *, diropres*);
+#elif __STDC__
+extern bool_t xdr_diropres(XDR *, diropres*);
+#else /* Old Style C */
+bool_t xdr_diropres();
+#endif /* Old Style C */
+
+
+struct readlinkres {
+ nfsstat status;
+ union {
+ nfspath data;
+ } readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readlinkres(XDR *, readlinkres*);
+#elif __STDC__
+extern bool_t xdr_readlinkres(XDR *, readlinkres*);
+#else /* Old Style C */
+bool_t xdr_readlinkres();
+#endif /* Old Style C */
+
+
+struct readargs {
+ nfs_fh file;
+ u_int offset;
+ u_int count;
+ u_int totalcount;
+};
+typedef struct readargs readargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readargs(XDR *, readargs*);
+#elif __STDC__
+extern bool_t xdr_readargs(XDR *, readargs*);
+#else /* Old Style C */
+bool_t xdr_readargs();
+#endif /* Old Style C */
+
+
+struct readokres {
+ fattr attributes;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct readokres readokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readokres(XDR *, readokres*);
+#elif __STDC__
+extern bool_t xdr_readokres(XDR *, readokres*);
+#else /* Old Style C */
+bool_t xdr_readokres();
+#endif /* Old Style C */
+
+
+struct readres {
+ nfsstat status;
+ union {
+ readokres reply;
+ } readres_u;
+};
+typedef struct readres readres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readres(XDR *, readres*);
+#elif __STDC__
+extern bool_t xdr_readres(XDR *, readres*);
+#else /* Old Style C */
+bool_t xdr_readres();
+#endif /* Old Style C */
+
+
+struct writeargs {
+ nfs_fh file;
+ u_int beginoffset;
+ u_int offset;
+ u_int totalcount;
+ struct {
+ u_int data_len;
+ char *data_val;
+ } data;
+};
+typedef struct writeargs writeargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_writeargs(XDR *, writeargs*);
+#elif __STDC__
+extern bool_t xdr_writeargs(XDR *, writeargs*);
+#else /* Old Style C */
+bool_t xdr_writeargs();
+#endif /* Old Style C */
+
+
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+typedef struct createargs createargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_createargs(XDR *, createargs*);
+#elif __STDC__
+extern bool_t xdr_createargs(XDR *, createargs*);
+#else /* Old Style C */
+bool_t xdr_createargs();
+#endif /* Old Style C */
+
+
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+typedef struct renameargs renameargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_renameargs(XDR *, renameargs*);
+#elif __STDC__
+extern bool_t xdr_renameargs(XDR *, renameargs*);
+#else /* Old Style C */
+bool_t xdr_renameargs();
+#endif /* Old Style C */
+
+
+struct linkargs {
+ nfs_fh from;
+ diropargs to;
+};
+typedef struct linkargs linkargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_linkargs(XDR *, linkargs*);
+#elif __STDC__
+extern bool_t xdr_linkargs(XDR *, linkargs*);
+#else /* Old Style C */
+bool_t xdr_linkargs();
+#endif /* Old Style C */
+
+
+struct symlinkargs {
+ diropargs from;
+ nfspath to;
+ sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#elif __STDC__
+extern bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#else /* Old Style C */
+bool_t xdr_symlinkargs();
+#endif /* Old Style C */
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+#ifdef __cplusplus
+extern "C" bool_t xdr_nfscookie(XDR *, nfscookie);
+#elif __STDC__
+extern bool_t xdr_nfscookie(XDR *, nfscookie);
+#else /* Old Style C */
+bool_t xdr_nfscookie();
+#endif /* Old Style C */
+
+
+struct readdirargs {
+ nfs_fh dir;
+ nfscookie cookie;
+ u_int count;
+};
+typedef struct readdirargs readdirargs;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readdirargs(XDR *, readdirargs*);
+#elif __STDC__
+extern bool_t xdr_readdirargs(XDR *, readdirargs*);
+#else /* Old Style C */
+bool_t xdr_readdirargs();
+#endif /* Old Style C */
+
+
+struct entry {
+ u_int fileid;
+ filename name;
+ nfscookie cookie;
+ struct entry *nextentry;
+};
+typedef struct entry entry;
+#ifdef __cplusplus
+extern "C" bool_t xdr_entry(XDR *, entry*);
+#elif __STDC__
+extern bool_t xdr_entry(XDR *, entry*);
+#else /* Old Style C */
+bool_t xdr_entry();
+#endif /* Old Style C */
+
+
+struct dirlist {
+ entry *entries;
+ bool_t eof;
+};
+typedef struct dirlist dirlist;
+#ifdef __cplusplus
+extern "C" bool_t xdr_dirlist(XDR *, dirlist*);
+#elif __STDC__
+extern bool_t xdr_dirlist(XDR *, dirlist*);
+#else /* Old Style C */
+bool_t xdr_dirlist();
+#endif /* Old Style C */
+
+
+struct readdirres {
+ nfsstat status;
+ union {
+ dirlist reply;
+ } readdirres_u;
+};
+typedef struct readdirres readdirres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_readdirres(XDR *, readdirres*);
+#elif __STDC__
+extern bool_t xdr_readdirres(XDR *, readdirres*);
+#else /* Old Style C */
+bool_t xdr_readdirres();
+#endif /* Old Style C */
+
+
+struct statfsokres {
+ u_int tsize;
+ u_int bsize;
+ u_int blocks;
+ u_int bfree;
+ u_int bavail;
+};
+typedef struct statfsokres statfsokres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_statfsokres(XDR *, statfsokres*);
+#elif __STDC__
+extern bool_t xdr_statfsokres(XDR *, statfsokres*);
+#else /* Old Style C */
+bool_t xdr_statfsokres();
+#endif /* Old Style C */
+
+
+struct statfsres {
+ nfsstat status;
+ union {
+ statfsokres reply;
+ } statfsres_u;
+};
+typedef struct statfsres statfsres;
+#ifdef __cplusplus
+extern "C" bool_t xdr_statfsres(XDR *, statfsres*);
+#elif __STDC__
+extern bool_t xdr_statfsres(XDR *, statfsres*);
+#else /* Old Style C */
+bool_t xdr_statfsres();
+#endif /* Old Style C */
+
+#endif /*!_rpcsvc_nfs_prot_h*/
+
+#define NFS_PROGRAM ((u_long)100003)
+#define NFS_VERSION ((u_long)2)
+
+#ifdef __cplusplus
+#define NFSPROC_NULL ((u_long)0)
+extern "C" void * nfsproc_null_2(void *, CLIENT *);
+extern "C" void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern "C" attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern "C" attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern "C" attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern "C" attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern "C" void * nfsproc_root_2(void *, CLIENT *);
+extern "C" void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern "C" diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern "C" diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern "C" readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern "C" readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern "C" readres * nfsproc_read_2(readargs *, CLIENT *);
+extern "C" readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern "C" void * nfsproc_writecache_2(void *, CLIENT *);
+extern "C" void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern "C" attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern "C" attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern "C" diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern "C" nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern "C" nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern "C" nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern "C" nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern "C" diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern "C" nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern "C" readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern "C" readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern "C" statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern "C" statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#elif __STDC__
+#define NFSPROC_NULL ((u_long)0)
+extern void * nfsproc_null_2(void *, CLIENT *);
+extern void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern void * nfsproc_root_2(void *, CLIENT *);
+extern void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern readres * nfsproc_read_2(readargs *, CLIENT *);
+extern readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern void * nfsproc_writecache_2(void *, CLIENT *);
+extern void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#else /* Old Style C */
+#define NFSPROC_NULL ((u_long)0)
+extern void * nfsproc_null_2();
+extern void * nfsproc_null_2_svc();
+#define NFSPROC_GETATTR ((u_long)1)
+extern attrstat * nfsproc_getattr_2();
+extern attrstat * nfsproc_getattr_2_svc();
+#define NFSPROC_SETATTR ((u_long)2)
+extern attrstat * nfsproc_setattr_2();
+extern attrstat * nfsproc_setattr_2_svc();
+#define NFSPROC_ROOT ((u_long)3)
+extern void * nfsproc_root_2();
+extern void * nfsproc_root_2_svc();
+#define NFSPROC_LOOKUP ((u_long)4)
+extern diropres * nfsproc_lookup_2();
+extern diropres * nfsproc_lookup_2_svc();
+#define NFSPROC_READLINK ((u_long)5)
+extern readlinkres * nfsproc_readlink_2();
+extern readlinkres * nfsproc_readlink_2_svc();
+#define NFSPROC_READ ((u_long)6)
+extern readres * nfsproc_read_2();
+extern readres * nfsproc_read_2_svc();
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern void * nfsproc_writecache_2();
+extern void * nfsproc_writecache_2_svc();
+#define NFSPROC_WRITE ((u_long)8)
+extern attrstat * nfsproc_write_2();
+extern attrstat * nfsproc_write_2_svc();
+#define NFSPROC_CREATE ((u_long)9)
+extern diropres * nfsproc_create_2();
+extern diropres * nfsproc_create_2_svc();
+#define NFSPROC_REMOVE ((u_long)10)
+extern nfsstat * nfsproc_remove_2();
+extern nfsstat * nfsproc_remove_2_svc();
+#define NFSPROC_RENAME ((u_long)11)
+extern nfsstat * nfsproc_rename_2();
+extern nfsstat * nfsproc_rename_2_svc();
+#define NFSPROC_LINK ((u_long)12)
+extern nfsstat * nfsproc_link_2();
+extern nfsstat * nfsproc_link_2_svc();
+#define NFSPROC_SYMLINK ((u_long)13)
+extern nfsstat * nfsproc_symlink_2();
+extern nfsstat * nfsproc_symlink_2_svc();
+#define NFSPROC_MKDIR ((u_long)14)
+extern diropres * nfsproc_mkdir_2();
+extern diropres * nfsproc_mkdir_2_svc();
+#define NFSPROC_RMDIR ((u_long)15)
+extern nfsstat * nfsproc_rmdir_2();
+extern nfsstat * nfsproc_rmdir_2_svc();
+#define NFSPROC_READDIR ((u_long)16)
+extern readdirres * nfsproc_readdir_2();
+extern readdirres * nfsproc_readdir_2_svc();
+#define NFSPROC_STATFS ((u_long)17)
+extern statfsres * nfsproc_statfs_2();
+extern statfsres * nfsproc_statfs_2_svc();
+#endif /* Old Style C */
+
+#endif /* !_NFS_PROT_H_RPCGEN */
diff --git a/kioslave/nfs/nfs_prot.x b/kioslave/nfs/nfs_prot.x
new file mode 100644
index 000000000..cd21123c7
--- /dev/null
+++ b/kioslave/nfs/nfs_prot.x
@@ -0,0 +1,365 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1987, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)nfs_prot.x 1.3 91/03/11 TIRPC 1.0 */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_nfs_prot_h
+%#define _rpcsvc_nfs_prot_h
+#endif
+
+const NFS_PORT = 2049;
+const NFS_MAXDATA = 8192;
+const NFS_MAXPATHLEN = 1024;
+const NFS_MAXNAMLEN = 255;
+const NFS_FHSIZE = 32;
+const NFS_COOKIESIZE = 4;
+const NFS_FIFO_DEV = -1; /* size kludge for named pipes */
+
+/*
+ * File types
+ */
+const NFSMODE_FMT = 0170000; /* type of file */
+const NFSMODE_DIR = 0040000; /* directory */
+const NFSMODE_CHR = 0020000; /* character special */
+const NFSMODE_BLK = 0060000; /* block special */
+const NFSMODE_REG = 0100000; /* regular */
+const NFSMODE_LNK = 0120000; /* symbolic link */
+const NFSMODE_SOCK = 0140000; /* socket */
+const NFSMODE_FIFO = 0010000; /* fifo */
+
+/*
+ * Error status
+ */
+enum nfsstat {
+ NFS_OK= 0, /* no error */
+ NFSERR_PERM=1, /* Not owner */
+ NFSERR_NOENT=2, /* No such file or directory */
+ NFSERR_IO=5, /* I/O error */
+ NFSERR_NXIO=6, /* No such device or address */
+ NFSERR_ACCES=13, /* Permission denied */
+ NFSERR_EXIST=17, /* File exists */
+ NFSERR_NODEV=19, /* No such device */
+ NFSERR_NOTDIR=20, /* Not a directory*/
+ NFSERR_ISDIR=21, /* Is a directory */
+ NFSERR_INVAL=22, /* invalid argument */
+ NFSERR_FBIG=27, /* File too large */
+ NFSERR_NOSPC=28, /* No space left on device */
+ NFSERR_ROFS=30, /* Read-only file system */
+ NFSERR_NAMETOOLONG=63, /* File name too long */
+ NFSERR_NOTEMPTY=66, /* Directory not empty */
+ NFSERR_DQUOT=69, /* Disc quota exceeded */
+ NFSERR_STALE=70, /* Stale NFS file handle */
+ NFSERR_WFLUSH=99 /* write cache flushed */
+};
+
+/*
+ * File types
+ */
+enum ftype {
+ NFNON = 0, /* non-file */
+ NFREG = 1, /* regular file */
+ NFDIR = 2, /* directory */
+ NFBLK = 3, /* block special */
+ NFCHR = 4, /* character special */
+ NFLNK = 5, /* symbolic link */
+ NFSOCK = 6, /* unix domain sockets */
+ NFBAD = 7, /* unused */
+ NFFIFO = 8 /* named pipe */
+};
+
+/*
+ * File access handle
+ */
+struct nfs_fh {
+ opaque data[NFS_FHSIZE];
+};
+
+/*
+ * Timeval
+ */
+struct nfstime {
+ unsigned seconds;
+ unsigned useconds;
+};
+
+
+/*
+ * File attributes
+ */
+struct fattr {
+ ftype type; /* file type */
+ unsigned mode; /* protection mode bits */
+ unsigned nlink; /* # hard links */
+ unsigned uid; /* owner user id */
+ unsigned gid; /* owner group id */
+ unsigned size; /* file size in bytes */
+ unsigned blocksize; /* prefered block size */
+ unsigned rdev; /* special device # */
+ unsigned blocks; /* Kb of disk used by file */
+ unsigned fsid; /* device # */
+ unsigned fileid; /* inode # */
+ nfstime atime; /* time of last access */
+ nfstime mtime; /* time of last modification */
+ nfstime ctime; /* time of last change */
+};
+
+/*
+ * File attributes which can be set
+ */
+struct sattr {
+ unsigned mode; /* protection mode bits */
+ unsigned uid; /* owner user id */
+ unsigned gid; /* owner group id */
+ unsigned size; /* file size in bytes */
+ nfstime atime; /* time of last access */
+ nfstime mtime; /* time of last modification */
+};
+
+
+typedef string filename<NFS_MAXNAMLEN>;
+typedef string nfspath<NFS_MAXPATHLEN>;
+
+/*
+ * Reply status with file attributes
+ */
+union attrstat switch (nfsstat status) {
+case NFS_OK:
+ fattr attributes;
+default:
+ void;
+};
+
+struct sattrargs {
+ nfs_fh file;
+ sattr attributes;
+};
+
+/*
+ * Arguments for directory operations
+ */
+struct diropargs {
+ nfs_fh dir; /* directory file handle */
+ filename name; /* name (up to NFS_MAXNAMLEN bytes) */
+};
+
+struct diropokres {
+ nfs_fh file;
+ fattr attributes;
+};
+
+/*
+ * Results from directory operation
+ */
+union diropres switch (nfsstat status) {
+case NFS_OK:
+ diropokres diropres;
+default:
+ void;
+};
+
+union readlinkres switch (nfsstat status) {
+case NFS_OK:
+ nfspath data;
+default:
+ void;
+};
+
+/*
+ * Arguments to remote read
+ */
+struct readargs {
+ nfs_fh file; /* handle for file */
+ unsigned offset; /* byte offset in file */
+ unsigned count; /* immediate read count */
+ unsigned totalcount; /* total read count (from this offset)*/
+};
+
+/*
+ * Status OK portion of remote read reply
+ */
+struct readokres {
+ fattr attributes; /* attributes, need for pagin*/
+ opaque data<NFS_MAXDATA>;
+};
+
+union readres switch (nfsstat status) {
+case NFS_OK:
+ readokres reply;
+default:
+ void;
+};
+
+/*
+ * Arguments to remote write
+ */
+struct writeargs {
+ nfs_fh file; /* handle for file */
+ unsigned beginoffset; /* beginning byte offset in file */
+ unsigned offset; /* current byte offset in file */
+ unsigned totalcount; /* total write count (to this offset)*/
+ opaque data<NFS_MAXDATA>;
+};
+
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+
+struct linkargs {
+ nfs_fh from;
+ diropargs to;
+};
+
+struct symlinkargs {
+ diropargs from;
+ nfspath to;
+ sattr attributes;
+};
+
+
+typedef opaque nfscookie[NFS_COOKIESIZE];
+
+/*
+ * Arguments to readdir
+ */
+struct readdirargs {
+ nfs_fh dir; /* directory handle */
+ nfscookie cookie;
+ unsigned count; /* number of directory bytes to read */
+};
+
+struct entry {
+ unsigned fileid;
+ filename name;
+ nfscookie cookie;
+ entry *nextentry;
+};
+
+struct dirlist {
+ entry *entries;
+ bool eof;
+};
+
+union readdirres switch (nfsstat status) {
+case NFS_OK:
+ dirlist reply;
+default:
+ void;
+};
+
+struct statfsokres {
+ unsigned tsize; /* preferred transfer size in bytes */
+ unsigned bsize; /* fundamental file system block size */
+ unsigned blocks; /* total blocks in file system */
+ unsigned bfree; /* free blocks in fs */
+ unsigned bavail; /* free blocks avail to non-superuser */
+};
+
+union statfsres switch (nfsstat status) {
+case NFS_OK:
+ statfsokres reply;
+default:
+ void;
+};
+
+/*
+ * Remote file service routines
+ */
+program NFS_PROGRAM {
+ version NFS_VERSION {
+ void
+ NFSPROC_NULL(void) = 0;
+
+ attrstat
+ NFSPROC_GETATTR(nfs_fh) = 1;
+
+ attrstat
+ NFSPROC_SETATTR(sattrargs) = 2;
+
+ void
+ NFSPROC_ROOT(void) = 3;
+
+ diropres
+ NFSPROC_LOOKUP(diropargs) = 4;
+
+ readlinkres
+ NFSPROC_READLINK(nfs_fh) = 5;
+
+ readres
+ NFSPROC_READ(readargs) = 6;
+
+ void
+ NFSPROC_WRITECACHE(void) = 7;
+
+ attrstat
+ NFSPROC_WRITE(writeargs) = 8;
+
+ diropres
+ NFSPROC_CREATE(createargs) = 9;
+
+ nfsstat
+ NFSPROC_REMOVE(diropargs) = 10;
+
+ nfsstat
+ NFSPROC_RENAME(renameargs) = 11;
+
+ nfsstat
+ NFSPROC_LINK(linkargs) = 12;
+
+ nfsstat
+ NFSPROC_SYMLINK(symlinkargs) = 13;
+
+ diropres
+ NFSPROC_MKDIR(createargs) = 14;
+
+ nfsstat
+ NFSPROC_RMDIR(diropargs) = 15;
+
+ readdirres
+ NFSPROC_READDIR(readdirargs) = 16;
+
+ statfsres
+ NFSPROC_STATFS(nfs_fh) = 17;
+ } = 2;
+} = 100003;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_nfs_prot_h*/
+#endif
diff --git a/kioslave/nfs/nfs_prot_xdr.c b/kioslave/nfs/nfs_prot_xdr.c
new file mode 100644
index 000000000..57d446489
--- /dev/null
+++ b/kioslave/nfs/nfs_prot_xdr.c
@@ -0,0 +1,886 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <arpa/inet.h>
+
+#include "nfs_prot.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1987, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)nfs_prot.x 1.3 91/03/11 TIRPC 1.0 */
+
+bool_t
+xdr_nfsstat(XDR *xdrs, nfsstat *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ftype(XDR *xdrs, ftype *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfs_fh(XDR *xdrs, nfs_fh *objp)
+{
+
+ register int32_t *buf=buf;
+
+ int i=i;
+ if (!xdr_opaque(xdrs, objp->data, NFS_FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfstime(XDR *xdrs, nfstime *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_u_int(xdrs, &objp->seconds)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->useconds)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_fattr(XDR *xdrs, fattr *objp)
+{
+
+ register int32_t *buf=buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_ftype(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs,10 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->nlink)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocksize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->rdev)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fsid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_U_LONG(buf,objp->mode);
+ IXDR_PUT_U_LONG(buf,objp->nlink);
+ IXDR_PUT_U_LONG(buf,objp->uid);
+ IXDR_PUT_U_LONG(buf,objp->gid);
+ IXDR_PUT_U_LONG(buf,objp->size);
+ IXDR_PUT_U_LONG(buf,objp->blocksize);
+ IXDR_PUT_U_LONG(buf,objp->rdev);
+ IXDR_PUT_U_LONG(buf,objp->blocks);
+ IXDR_PUT_U_LONG(buf,objp->fsid);
+ IXDR_PUT_U_LONG(buf,objp->fileid);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->ctime)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ if (!xdr_ftype(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs,10 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->nlink)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocksize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->rdev)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fsid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->mode = IXDR_GET_U_LONG(buf);
+ objp->nlink = IXDR_GET_U_LONG(buf);
+ objp->uid = IXDR_GET_U_LONG(buf);
+ objp->gid = IXDR_GET_U_LONG(buf);
+ objp->size = IXDR_GET_U_LONG(buf);
+ objp->blocksize = IXDR_GET_U_LONG(buf);
+ objp->rdev = IXDR_GET_U_LONG(buf);
+ objp->blocks = IXDR_GET_U_LONG(buf);
+ objp->fsid = IXDR_GET_U_LONG(buf);
+ objp->fileid = IXDR_GET_U_LONG(buf);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->ctime)) {
+ return (FALSE);
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_ftype(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->nlink)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocksize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->rdev)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fsid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->ctime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_sattr(XDR *xdrs, sattr *objp)
+{
+
+ register int32_t *buf=buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs,4 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_U_LONG(buf,objp->mode);
+ IXDR_PUT_U_LONG(buf,objp->uid);
+ IXDR_PUT_U_LONG(buf,objp->gid);
+ IXDR_PUT_U_LONG(buf,objp->size);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs,4 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->mode = IXDR_GET_U_LONG(buf);
+ objp->uid = IXDR_GET_U_LONG(buf);
+ objp->gid = IXDR_GET_U_LONG(buf);
+ objp->size = IXDR_GET_U_LONG(buf);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_u_int(xdrs, &objp->mode)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->uid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->gid)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->size)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->atime)) {
+ return (FALSE);
+ }
+ if (!xdr_nfstime(xdrs, &objp->mtime)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_filename(XDR *xdrs, filename *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_string(xdrs, objp, NFS_MAXNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfspath(XDR *xdrs, nfspath *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_string(xdrs, objp, NFS_MAXPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_attrstat(XDR *xdrs, attrstat *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_fattr(xdrs, &objp->attrstat_u.attributes)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_sattrargs(XDR *xdrs, sattrargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_diropargs(XDR *xdrs, diropargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->dir)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_diropokres(XDR *xdrs, diropokres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_fattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_diropres(XDR *xdrs, diropres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_diropokres(xdrs, &objp->diropres_u.diropres)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readlinkres(XDR *xdrs, readlinkres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_nfspath(xdrs, &objp->readlinkres_u.data)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readargs(XDR *xdrs, readargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readokres(XDR *xdrs, readokres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_fattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readres(XDR *xdrs, readres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_readokres(xdrs, &objp->readres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_writeargs(XDR *xdrs, writeargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs,3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->beginoffset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_U_LONG(buf,objp->beginoffset);
+ IXDR_PUT_U_LONG(buf,objp->offset);
+ IXDR_PUT_U_LONG(buf,objp->totalcount);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs,3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->beginoffset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->beginoffset = IXDR_GET_U_LONG(buf);
+ objp->offset = IXDR_GET_U_LONG(buf);
+ objp->totalcount = IXDR_GET_U_LONG(buf);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_nfs_fh(xdrs, &objp->file)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->beginoffset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->offset)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->totalcount)) {
+ return (FALSE);
+ }
+ if (!xdr_bytes(xdrs, (char **)&objp->data.data_val, (u_int *)&objp->data.data_len, NFS_MAXDATA)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_createargs(XDR *xdrs, createargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_diropargs(xdrs, &objp->where)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_renameargs(XDR *xdrs, renameargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_diropargs(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_linkargs(XDR *xdrs, linkargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_diropargs(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_symlinkargs(XDR *xdrs, symlinkargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_diropargs(xdrs, &objp->from)) {
+ return (FALSE);
+ }
+ if (!xdr_nfspath(xdrs, &objp->to)) {
+ return (FALSE);
+ }
+ if (!xdr_sattr(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_nfscookie(XDR *xdrs, nfscookie objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_opaque(xdrs, objp, NFS_COOKIESIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readdirargs(XDR *xdrs, readdirargs *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfs_fh(xdrs, &objp->dir)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_entry(XDR *xdrs, entry *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_u_int(xdrs, &objp->fileid)) {
+ return (FALSE);
+ }
+ if (!xdr_filename(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ if (!xdr_nfscookie(xdrs, objp->cookie)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, &objp->nextentry, sizeof(entry), (xdrproc_t)xdr_entry)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_dirlist(XDR *xdrs, dirlist *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_pointer(xdrs, (char **)&objp->entries, sizeof(entry), (xdrproc_t)xdr_entry)) {
+ return (FALSE);
+ }
+ if (!xdr_bool(xdrs, &objp->eof)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_readdirres(XDR *xdrs, readdirres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_dirlist(xdrs, &objp->readdirres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_statfsokres(XDR *xdrs, statfsokres *objp)
+{
+
+ register int32_t *buf=buf;
+
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->tsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bfree)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bavail)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_U_LONG(buf,objp->tsize);
+ IXDR_PUT_U_LONG(buf,objp->bsize);
+ IXDR_PUT_U_LONG(buf,objp->blocks);
+ IXDR_PUT_U_LONG(buf,objp->bfree);
+ IXDR_PUT_U_LONG(buf,objp->bavail);
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int(xdrs, &objp->tsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bfree)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bavail)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->tsize = IXDR_GET_U_LONG(buf);
+ objp->bsize = IXDR_GET_U_LONG(buf);
+ objp->blocks = IXDR_GET_U_LONG(buf);
+ objp->bfree = IXDR_GET_U_LONG(buf);
+ objp->bavail = IXDR_GET_U_LONG(buf);
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_u_int(xdrs, &objp->tsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bsize)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->blocks)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bfree)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->bavail)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_statfsres(XDR *xdrs, statfsres *objp)
+{
+
+ register int32_t *buf=buf;
+
+ if (!xdr_nfsstat(xdrs, &objp->status)) {
+ return (FALSE);
+ }
+ switch (objp->status) {
+ case NFS_OK:
+ if (!xdr_statfsokres(xdrs, &objp->statfsres_u.reply)) {
+ return (FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}