diff options
Diffstat (limited to 'kioslave/nfs/kio_nfs.cpp')
-rw-r--r-- | kioslave/nfs/kio_nfs.cpp | 1615 |
1 files changed, 0 insertions, 1615 deletions
diff --git a/kioslave/nfs/kio_nfs.cpp b/kioslave/nfs/kio_nfs.cpp deleted file mode 100644 index b28f3d61e..000000000 --- a/kioslave/nfs/kio_nfs.cpp +++ /dev/null @@ -1,1615 +0,0 @@ -/* This file is part of the KDE project - - Copyright (C) 2000 Alexander Neundorf <[email protected]> - - 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 <tqfile.h> -#include <tqdir.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 TDEIO; -using namespace std; - -//this is taken from tdelibs/tdecore/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 ) -{ - TDEInstance 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 TQString& path) -{ - return (path.isEmpty() || (path=="/")); -} - -static bool isAbsoluteLink(const TQString& 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 = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - atom.m_str = "root"; - entry.append( atom ); - atom.m_uds = TDEIO::UDS_GROUP; - atom.m_str = "root"; - entry.append( atom ); - - //a dummy size - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = 1024; - entry.append( atom ); -} - - -static void stripTrailingSlash(TQString& path) -{ - //if (path=="/") return; - if (path=="/") path=""; - else if (path[path.length()-1]=='/') path.truncate(path.length()-1); -} - -static void getLastPart(const TQString& path, TQString& lastPart, TQString& rest) -{ - int slashPos=path.findRev("/"); - lastPart=path.mid(slashPos+1); - rest=path.left(slashPos+1); -} - -static TQString removeFirstPart(const TQString& path) -{ - TQString 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 TQCString &pool, const TQCString &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 TQString& 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(TQString 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]; - } - TQString 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); - TQCString tmpStr=TQFile::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; - } - } - TQCString 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 tdelibs/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; - TQString fname; - if ( exportlist->ex_dir[0] == '/' ) - fname = TDEIO::encodeFileName(exportlist->ex_dir + 1); - else - fname = TDEIO::encodeFileName(exportlist->ex_dir); - m_handleCache.insert(TQString("/")+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); - TQString path( TQFile::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 (TQStringList::Iterator it=m_exportedDirs.begin(); it!=m_exportedDirs.end(); it++) - { - UDSAtom atom; - entry.clear(); - atom.m_uds = TDEIO::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; - } - - TQStringList 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 ((TQString(".")!=dirEntry->name) && (TQString("..")!=dirEntry->name)) - filesToList.append(dirEntry->name); - } - } while (!listres.readdirres_u.reply.eof); - totalSize( filesToList.count()); - - UDSEntry entry; - //stat all files in filesToList - for (TQStringList::Iterator it=filesToList.begin(); it!=filesToList.end(); it++) - { - UDSAtom atom; - diropargs dirargs; - diropres dirres; - memcpy(dirargs.dir.data,fh,NFS_FHSIZE); - TQCString tmpStr=TQFile::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 = TDEIO::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; - TQCString linkDest(readLinkRes.readlinkres_u.data); - atom.m_uds = TDEIO::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=TQDir::cleanDirPath(path+TQString("/")+TQString(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) -{ - TQString path( TQFile::encodeName(url.path())); - stripTrailingSlash(path); - kdDebug(7121)<<"NFS::stat for -"<<path<<"-"<<endl; - TQString 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 = TDEIO::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); - TQCString tmpStr=TQFile::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; - - TQString fileName, parentDir; - getLastPart(path, fileName, parentDir); - stripTrailingSlash(parentDir); - - atom.m_uds = TDEIO::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; - TQCString linkDest(readLinkRes.readlinkres_u.data); - atom.m_uds = TDEIO::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=TQDir::cleanDirPath(parentDir+TQString("/")+TQString(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 TQCString& path) -{ - //taken from file.cc - struct stat buff; - if ( ::stat( path.data(), &buff ) == -1 ) return; - - UDSAtom atom; - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = buff.st_mode & S_IFMT; // extract file type - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = buff.st_mode & 07777; // extract permissions - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = buff.st_size; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; - atom.m_long = buff.st_mtime; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - uid_t uid = buff.st_uid; - TQString *temp = m_usercache.find( uid ); - - if ( !temp ) - { - struct passwd *user = getpwuid( uid ); - if ( user ) - { - m_usercache.insert( uid, new TQString(TQString::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 = TDEIO::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 TQString(TQString::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 = TDEIO::UDS_ACCESS_TIME; - atom.m_long = buff.st_atime; - entry.append( atom ); - - atom.m_uds = TDEIO::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 = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFMT - 1; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRWXU | S_IRWXG | S_IRWXO; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = 0L; - entry.append( atom ); -} - -void NFSProtocol::completeUDSEntry(UDSEntry& entry, fattr& attributes) -{ - UDSAtom atom; - - atom.m_uds = TDEIO::UDS_SIZE; - atom.m_long = attributes.size; - entry.append(atom); - - atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; - atom.m_long = attributes.mtime.seconds; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS_TIME; - atom.m_long = attributes.atime.seconds; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_CREATION_TIME; - atom.m_long = attributes.ctime.seconds; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = (attributes.mode & 07777); - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long =attributes.mode & S_IFMT; // extract file type - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - uid_t uid = attributes.uid; - TQString *temp = m_usercache.find( uid ); - if ( !temp ) - { - struct passwd *user = getpwuid( uid ); - if ( user ) - { - m_usercache.insert( uid, new TQString(user->pw_name) ); - atom.m_str = user->pw_name; - } - else - atom.m_str = "???"; - } - else - atom.m_str = *temp; - entry.append( atom ); - - atom.m_uds = TDEIO::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 TQString(grp->gr_name) ); - atom.m_str = grp->gr_name; - } - else - atom.m_str = "???"; - } - else - atom.m_str = *temp; - entry.append( atom ); - -/* TDEIO::UDSEntry::ConstIterator it = entry.begin(); - for( ; it != entry.end(); it++ ) { - switch ((*it).m_uds) { - case TDEIO::UDS_FILE_TYPE: - kdDebug(7121) << "File Type : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_ACCESS: - kdDebug(7121) << "Access permissions : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_USER: - kdDebug(7121) << "User : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_GROUP: - kdDebug(7121) << "Group : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_NAME: - kdDebug(7121) << "Name : " << ((*it).m_str.ascii() ) << endl; - //m_strText = decodeFileName( (*it).m_str ); - break; - case TDEIO::UDS_URL: - kdDebug(7121) << "URL : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_MIME_TYPE: - kdDebug(7121) << "MimeType : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_LINK_DEST: - kdDebug(7121) << "LinkDest : " << ((*it).m_str.ascii() ) << endl; - break; - } - }*/ -} - -void NFSProtocol::setHost(const TQString& host, int /*port*/, const TQString& /*user*/, const TQString& /*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; - TQString thePath( TQFile::encodeName(url.path())); - stripTrailingSlash(thePath); - TQString 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); - TQCString tmpName=TQFile::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 TQString& 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) -{ - TQString thePath( TQFile::encodeName(url.path())); - stripTrailingSlash(thePath); - - TQString 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); - TQCString tmpName=TQFile::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); - TQCString tmpName=TQFile::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 ) -{ - TQString thePath( TQFile::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 ) -{ - TQString thePath( TQFile::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; - - TQByteArray 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( TQByteArray() ); - finished(); -} - -//TODO the partial putting thing is not yet implemented -void NFSProtocol::put( const KURL& url, int _mode, bool _overwrite, bool /*_resume*/ ) -{ - TQString destPath( TQFile::encodeName(url.path())); - kdDebug( 7121 ) << "Put -" << destPath <<"-"<<endl; - /*TQString dest_part( dest_orig ); - dest_part += ".part";*/ - - stripTrailingSlash(destPath); - TQString 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); - TQCString tmpName=TQFile::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 - { - TQByteArray 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 ) -{ - TQString srcPath( TQFile::encodeName(src.path())); - TQString destPath( TQFile::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; - } - } - - TQString 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); - TQCString tmpName=TQFile::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); - TQCString tmpName2=TQFile::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 - TQString thePath( TQFile::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 - TQString destPath( TQFile::encodeName(dest.path())); - stripTrailingSlash(destPath); - TQString 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); - TQCString tmpName=TQFile::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 TQString &target, const KURL &dest, bool ) -{ - kdDebug(7121)<<"symlinking "<<endl; - TQString destPath=dest.path(); - stripTrailingSlash(destPath); - - TQString 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; - TQCString tmpStr=target.latin1(); - symlinkargs symLinkArgs; - symLinkArgs.to=tmpStr.data(); - memcpy(symLinkArgs.from.dir.data,(const char*)fh,NFS_FHSIZE); - TQCString tmpStr2=TQFile::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 TQString& parentDir, const TQString& 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 TQFile::exists(linkDest); - } - else - { - kdDebug(7121)<<"is a relative link"<<endl; - TQString absDest=parentDir+"/"+linkDest; - kdDebug(7121)<<"pointing abs to "<<absDest<<endl; - absDest=removeFirstPart(absDest); - kdDebug(7121)<<"removed first part "<<absDest<<endl; - absDest=TQDir::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=TQDir::cleanDirPath(absDest); - kdDebug(7121)<<"getting file handle of "<<absDest<<endl; - NFSFileHandle fh=getFileHandle(absDest); - return (!fh.isInvalid()); - } - return FALSE; -} - |