diff options
author | Memphiz <memphis@machzwo.de> | 2011-07-18 23:39:27 +0200 |
---|---|---|
committer | Memphiz <memphis@machzwo.de> | 2011-07-18 23:39:27 +0200 |
commit | 6713a158ead605d6faf006e4fd1956ae7bbb84c9 (patch) | |
tree | bdfab50fc0d22a26293c35d162d728d33277d61a | |
parent | 43a13d3bf8eaf49da153a697cb8f0a63f63aba8f (diff) |
[add] - added support for dns name resolution
- refactored gNfsConnection
- added missing GPL headers
- refactored GetDirectory / added GetDirectoryFromExportList
- reduce number of mount requests to a minimum by using the list of exported pathes from the server
- added support for listing nfs servers of the subnet (url nfs://)
- nfs support knows kung fu now :D
-rw-r--r-- | lib/libnfs/Makefile | 3 | ||||
-rw-r--r-- | xbmc/filesystem/FileNFS.cpp | 257 | ||||
-rw-r--r-- | xbmc/filesystem/FileNFS.h | 56 | ||||
-rw-r--r-- | xbmc/filesystem/NFSDirectory.cpp | 124 | ||||
-rw-r--r-- | xbmc/filesystem/NFSDirectory.h | 19 |
5 files changed, 318 insertions, 141 deletions
diff --git a/lib/libnfs/Makefile b/lib/libnfs/Makefile index cc3e4220c8..5eee588f87 100644 --- a/lib/libnfs/Makefile +++ b/lib/libnfs/Makefile @@ -18,7 +18,8 @@ ARCHIVE_TOOL=tar ARCHIVE_TOOL_FLAGS=xf # configuration settings -CONFIGURE=./configure +#FIX THE PREFIX TO SOMETHING LOCAL IN XBMC - CONFIGURE HAS TO FIND IT! +CONFIGURE=./configure --prefix=/usr SO_NAME=$(SOURCE)/lib/libnfs.so diff --git a/xbmc/filesystem/FileNFS.cpp b/xbmc/filesystem/FileNFS.cpp index 74252553b0..51cf3f44ae 100644 --- a/xbmc/filesystem/FileNFS.cpp +++ b/xbmc/filesystem/FileNFS.cpp @@ -30,12 +30,16 @@ #include "threads/SingleLock.h" #include "utils/log.h" #include "utils/URIUtils.h" +#include "nfsc/libnfs-raw-mount.h" +#include "network/DNSNameCache.h" using namespace XFILE; CNfsConnection::CNfsConnection() : m_pNfsContext(NULL) -, m_shareName("") +, m_exportPath("") +, m_hostName("") +, m_resolvedHostName("") , m_readChunkSize(0) , m_writeChunkSize(0) , m_OpenConnections(0) @@ -46,79 +50,174 @@ CNfsConnection::CNfsConnection() CNfsConnection::~CNfsConnection() { + Deinit(); delete m_pLibNfs; } -void CNfsConnection::resetContext() +void CNfsConnection::resolveHost(const CURL &url) +{ + //resolve if hostname has changed + if( !url.GetHostName().Equals(m_hostName) ) + { + CDNSNameCache::Lookup(url.GetHostName(), m_resolvedHostName); + } +} + +std::list<CStdString> CNfsConnection::GetExportList(const CURL &url) { + std::list<CStdString> retList; + + if(HandleDyLoad()) + { + struct exportnode *exportlist, *tmp; + exportlist = m_pLibNfs->mount_getexports(m_resolvedHostName); + tmp = exportlist; + + for(tmp = exportlist; tmp!=NULL; tmp=tmp->ex_next) + { + retList.push_back(CStdString(tmp->ex_dir)); + } + + gNfsConnection.GetImpl()->mount_free_export_list(exportlist); + } + + return retList; +} + +bool CNfsConnection::HandleDyLoad() +{ + bool ret = true; if(!m_pLibNfs->IsLoaded()) { if(!m_pLibNfs->Load()) { CLog::Log(LOGERROR,"NFS: Error loading libnfs (%s).",__FUNCTION__); - return;//FATAL! + ret = false; //fatal } } - - if(m_pNfsContext) - { - m_pLibNfs->nfs_destroy_context(m_pNfsContext); - } - - m_pNfsContext = m_pLibNfs->nfs_init_context(); - - if (!m_pNfsContext) + return ret; +} + +void CNfsConnection::clearMembers() +{ + m_exportPath.clear(); + m_hostName.clear(); + m_exportList.clear(); + m_writeChunkSize = 0; + m_readChunkSize = 0; + m_pNfsContext = NULL; +} + +bool CNfsConnection::resetContext() +{ + bool ret = HandleDyLoad(); + + if(ret) { - CLog::Log(LOGERROR,"NFS: Error initcontext in resetContext."); + if(m_pNfsContext) + { + m_pLibNfs->nfs_destroy_context(m_pNfsContext); + } + + clearMembers(); + m_pNfsContext = m_pLibNfs->nfs_init_context(); + + if (!m_pNfsContext) + { + CLog::Log(LOGERROR,"NFS: Error initcontext in resetContext."); + ret = false; + } } - m_writeChunkSize = 0; - m_readChunkSize = 0; - m_shareName.clear(); - m_hostName.clear(); + return ret; +} + +bool CNfsConnection::splitUrlIntoExportAndPath(const CURL& url, CStdString &exportPath, CStdString &relativePath) +{ + bool ret = false; + + if(m_exportList.empty()) + { + m_exportList = GetExportList(url); + } + + if(!m_exportList.empty()) + { + relativePath = ""; + exportPath = ""; + + CStdString path = url.GetFileName(); + + //GetFileName returns path without leading "/" + //but we need it because the export paths start with "/" + //and path.Find(*it) wouldn't work else + if(path[0] != '/') + { + path = "/" + path; + } + + std::list<CStdString>::iterator it; + + for(it=m_exportList.begin();it!=m_exportList.end();it++) + { + //if path starts with the current export path + if( path.Find(*it) == 0 ) + { + exportPath = *it; + relativePath = "//" + path.Right((path.length()-1) - exportPath.length()); + ret = true; + break; + } + } + } + return ret; } -bool CNfsConnection::Connect(const CURL& url) +bool CNfsConnection::Connect(const CURL& url, CStdString &relativePath) { CSingleLock lock(*this); - int ret = 0; - CStdString share; - URIUtils::GetDirectory(url.GetFileName(),share); - share = "/" + share; + bool ret = false; + int nfsRet = 0; + CStdString exportPath = ""; - if(!share.Equals(m_shareName,true) || !url.GetHostName().Equals(m_hostName,false) ) + resolveHost(url); + ret = splitUrlIntoExportAndPath(url, exportPath, relativePath); + + if(ret && (!exportPath.Equals(m_exportPath,true) || !url.GetHostName().Equals(m_hostName,false)) ) { - resetContext();//we need a new context because sharename or hostname has changed - old context will be freed + if(!resetContext())//we need a new context because sharename or hostname has changed - old context will be freed + { + return false; + } //we connect to the directory of the path. This will be the "root" path of this connection then. //So all fileoperations are relative to this mountpoint... - ret = m_pLibNfs->nfs_mount_sync(m_pNfsContext, url.GetHostName().c_str(), share.c_str()); + nfsRet = m_pLibNfs->nfs_mount(m_pNfsContext, m_resolvedHostName.c_str(), exportPath.c_str()); - if (ret != 0) + if (nfsRet != 0) { - CLog::Log(LOGERROR,"NFS: Failed to mount nfs share: %s\n", m_pLibNfs->nfs_get_error(m_pNfsContext)); + CLog::Log(LOGERROR,"NFS: Failed to mount nfs share: %s (%s)\n", exportPath.c_str(), m_pLibNfs->nfs_get_error(m_pNfsContext)); return false; } - m_shareName = share; + m_exportPath = exportPath; m_hostName = url.GetHostName(); + //read chunksize only works after mount m_readChunkSize = m_pLibNfs->nfs_get_readmax(m_pNfsContext); m_writeChunkSize = m_pLibNfs->nfs_get_writemax(m_pNfsContext); - CLog::Log(LOGDEBUG,"NFS: Connected to server %s and export %s (chunks: r/w %i/%i)\n", url.GetHostName().c_str(), url.GetShareName().c_str(),(int)m_readChunkSize,(int)m_writeChunkSize); + + CLog::Log(LOGDEBUG,"NFS: Connected to server %s and export %s (chunks: r/w %i/%i)\n", url.GetHostName().c_str(), exportPath.c_str(),(int)m_readChunkSize,(int)m_writeChunkSize); } - - return true; + return ret; } void CNfsConnection::Deinit() { - if(m_pNfsContext) + if(m_pNfsContext && m_pLibNfs->IsLoaded()) { m_pLibNfs->nfs_destroy_context(m_pNfsContext); + m_pLibNfs->Unload(); } - m_pNfsContext = NULL; - m_shareName.clear(); - m_hostName.clear(); - m_pLibNfs->Unload(); + clearMembers(); } /* This is called from CApplication::ProcessSlow() and is used to tell if nfs have been idle for too long */ @@ -193,7 +292,7 @@ int64_t CFileNFS::GetPosition() if (gNfsConnection.GetNfsContext() == NULL || m_pFileHandle == NULL) return 0; - ret = (int)gNfsConnection.GetImpl()->nfs_lseek_sync(gNfsConnection.GetNfsContext(), m_pFileHandle, 0, SEEK_CUR, &offset); + ret = (int)gNfsConnection.GetImpl()->nfs_lseek(gNfsConnection.GetNfsContext(), m_pFileHandle, 0, SEEK_CUR, &offset); if (ret < 0) { @@ -220,14 +319,14 @@ bool CFileNFS::Open(const CURL& url) return false; } - CStdString filename = "//" + URIUtils::GetFileName(url.GetFileName()); + CStdString filename = ""; CSingleLock lock(gNfsConnection); - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url, filename)) return false; - ret = gNfsConnection.GetImpl()->nfs_open_sync(gNfsConnection.GetNfsContext(), filename.c_str(), O_RDONLY, &m_pFileHandle); + ret = gNfsConnection.GetImpl()->nfs_open(gNfsConnection.GetNfsContext(), filename.c_str(), O_RDONLY, &m_pFileHandle); if (ret != 0) { @@ -271,15 +370,15 @@ int CFileNFS::Stat(const CURL& url, struct __stat64* buffer) { int ret = 0; CSingleLock lock(gNfsConnection); + CStdString filename = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,filename)) return -1; - CStdString filename = "//" + URIUtils::GetFileName(url.GetFileName()); struct stat tmpBuffer = {0}; - ret = gNfsConnection.GetImpl()->nfs_stat_sync(gNfsConnection.GetNfsContext(), filename.c_str(), &tmpBuffer); + ret = gNfsConnection.GetImpl()->nfs_stat(gNfsConnection.GetNfsContext(), filename.c_str(), &tmpBuffer); //if buffer == NULL we where called from Exists - in that case don't spam the log with errors if (ret != 0 && buffer != NULL) @@ -311,38 +410,16 @@ int CFileNFS::Stat(const CURL& url, struct __stat64* buffer) unsigned int CFileNFS::Read(void *lpBuf, int64_t uiBufSize) { int numberOfBytesRead = 0; - int bytesLeft = uiBufSize; - int bytesRead = 0; - int chunkSize = gNfsConnection.GetMaxReadChunkSize(); CSingleLock lock(gNfsConnection); if (m_pFileHandle == NULL || gNfsConnection.GetNfsContext()==NULL ) return 0; - //read chunked since nfs will only give server specific packet sizes at once - while(bytesLeft) + numberOfBytesRead = gNfsConnection.GetImpl()->nfs_read(gNfsConnection.GetNfsContext(), m_pFileHandle, uiBufSize, (char *)lpBuf); + //something went wrong ... + if (numberOfBytesRead < 0) { - //last chunk could be smaller then chunk size - if(bytesLeft < chunkSize) - { - chunkSize = bytesLeft; - } - - bytesRead = gNfsConnection.GetImpl()->nfs_read_sync(gNfsConnection.GetNfsContext(), m_pFileHandle, chunkSize, (char *)lpBuf+numberOfBytesRead); - bytesLeft -= bytesRead; - numberOfBytesRead += bytesRead; - - if(bytesRead == 0) - { - break; //EOF - } - - //something went wrong ... - if (bytesRead < 0) - { - CLog::Log(LOGERROR, "%s - Error( %d, %s )", __FUNCTION__, bytesRead, gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); - return 0; - } - + CLog::Log(LOGERROR, "%s - Error( %d, %s )", __FUNCTION__, numberOfBytesRead, gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); + return 0; } return (unsigned int)numberOfBytesRead; } @@ -356,7 +433,7 @@ int64_t CFileNFS::Seek(int64_t iFilePosition, int iWhence) if (m_pFileHandle == NULL || gNfsConnection.GetNfsContext()==NULL) return -1; - ret = (int)gNfsConnection.GetImpl()->nfs_lseek_sync(gNfsConnection.GetNfsContext(), m_pFileHandle, iFilePosition, iWhence, &offset); + ret = (int)gNfsConnection.GetImpl()->nfs_lseek(gNfsConnection.GetNfsContext(), m_pFileHandle, iFilePosition, iWhence, &offset); if (ret < 0) { @@ -374,7 +451,7 @@ void CFileNFS::Close() { int ret = 0; CLog::Log(LOGDEBUG,"CFileNFS::Close closing file %s", m_url.GetFileName().c_str()); - ret = gNfsConnection.GetImpl()->nfs_close_sync(gNfsConnection.GetNfsContext(), m_pFileHandle); + ret = gNfsConnection.GetImpl()->nfs_close(gNfsConnection.GetNfsContext(), m_pFileHandle); if (ret < 0) { @@ -408,7 +485,7 @@ int CFileNFS::Write(const void* lpBuf, int64_t uiBufSize) chunkSize = leftBytes;//write last chunk with correct size } //write chunk - writtenBytes = gNfsConnection.GetImpl()->nfs_write_sync(gNfsConnection.GetNfsContext(), + writtenBytes = gNfsConnection.GetImpl()->nfs_write(gNfsConnection.GetNfsContext(), m_pFileHandle, (size_t)chunkSize, (char *)lpBuf + numberOfBytesWritten); @@ -432,13 +509,13 @@ bool CFileNFS::Delete(const CURL& url) { int ret = 0; CSingleLock lock(gNfsConnection); + CStdString filename = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url, filename)) return false; - CStdString filename = "//" + URIUtils::GetFileName(url.GetFileName()); - ret = gNfsConnection.GetImpl()->nfs_unlink_sync(gNfsConnection.GetNfsContext(), filename.c_str()); + ret = gNfsConnection.GetImpl()->nfs_unlink(gNfsConnection.GetNfsContext(), filename.c_str()); if(ret != 0) { @@ -451,14 +528,16 @@ bool CFileNFS::Rename(const CURL& url, const CURL& urlnew) { int ret = 0; CSingleLock lock(gNfsConnection); + CStdString strFile = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,strFile)) return false; - CStdString strFile = "//" + URIUtils::GetFileName(url.GetFileName()); - CStdString strFileNew = "//" + URIUtils::GetFileName(urlnew.GetFileName()); + CStdString strFileNew; + CStdString strDummy; + gNfsConnection.splitUrlIntoExportAndPath(urlnew, strDummy, strFileNew); - ret = gNfsConnection.GetImpl()->nfs_rename_sync(gNfsConnection.GetNfsContext() , strFile.c_str(), strFileNew.c_str()); + ret = gNfsConnection.GetImpl()->nfs_rename(gNfsConnection.GetNfsContext() , strFile.c_str(), strFileNew.c_str()); if(ret != 0) { @@ -470,32 +549,30 @@ bool CFileNFS::Rename(const CURL& url, const CURL& urlnew) bool CFileNFS::OpenForWrite(const CURL& url, bool bOverWrite) { int ret = 0; + // we can't open files like nfs://file.f or nfs://server/file.f + // if a file matches the if below return false, it can't exist on a nfs share. + if (!IsValidFile(url.GetFileName())) return false; Close(); CSingleLock lock(gNfsConnection); + CStdString filename = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,filename)) return false; - // we can't open files like nfs://file.f or nfs://server/file.f - // if a file matches the if below return false, it can't exist on a nfs share. - if (!IsValidFile(url.GetFileName())) return false; - - CStdString filename = "//" + URIUtils::GetFileName(url.GetFileName()); - if (bOverWrite) { CLog::Log(LOGWARNING, "FileNFS::OpenForWrite() called with overwriting enabled! - %s", filename.c_str()); //create file with proper permissions - ret = gNfsConnection.GetImpl()->nfs_creat_sync(gNfsConnection.GetNfsContext(), filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &m_pFileHandle); + ret = gNfsConnection.GetImpl()->nfs_creat(gNfsConnection.GetNfsContext(), filename.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &m_pFileHandle); //if file was created the file handle isn't valid ... so close it and open later if(ret == 0) { - gNfsConnection.GetImpl()->nfs_close_sync(gNfsConnection.GetNfsContext(),m_pFileHandle); + gNfsConnection.GetImpl()->nfs_close(gNfsConnection.GetNfsContext(),m_pFileHandle); } } - ret = gNfsConnection.GetImpl()->nfs_open_sync(gNfsConnection.GetNfsContext(), filename.c_str(), O_RDWR, &m_pFileHandle); + ret = gNfsConnection.GetImpl()->nfs_open(gNfsConnection.GetNfsContext(), filename.c_str(), O_RDWR, &m_pFileHandle); if (ret || m_pFileHandle == NULL) { diff --git a/xbmc/filesystem/FileNFS.h b/xbmc/filesystem/FileNFS.h index f62d902df3..d09f2b8348 100644 --- a/xbmc/filesystem/FileNFS.h +++ b/xbmc/filesystem/FileNFS.h @@ -1,3 +1,23 @@ +/* + * Copyright (C) 2011 Team XBMC + * http://www.xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ // FileNFS.h: interface for the CFileNFS class. #ifndef FILENFS_H_ @@ -6,6 +26,8 @@ #include "IFile.h" #include "URL.h" #include "threads/CriticalSection.h" +#include <list> +#include "SectionLoader.h" class DllLibNfs; @@ -15,28 +37,38 @@ public: CNfsConnection(); ~CNfsConnection(); - bool Connect(const CURL &url); + bool Connect(const CURL &url, CStdString &relativePath); struct nfs_context *GetNfsContext(){return m_pNfsContext;} size_t GetMaxReadChunkSize(){return m_readChunkSize;} size_t GetMaxWriteChunkSize(){return m_writeChunkSize;} DllLibNfs *GetImpl(){return m_pLibNfs;} - + std::list<CStdString> GetExportList(const CURL &url); + //this functions splits the url into the exportpath (feed to mount) and the rest of the path + //relative to the mounted export + bool splitUrlIntoExportAndPath(const CURL& url, CStdString &exportPath, CStdString &relativePath); + void AddActiveConnection(); void AddIdleConnection(); void CheckIfIdle(); void SetActivityTime(); void Deinit(); - + bool HandleDyLoad();//loads the lib if needed + private: - struct nfs_context *m_pNfsContext; - CStdString m_shareName; - CStdString m_hostName; - size_t m_readChunkSize; - size_t m_writeChunkSize; - int m_OpenConnections; - unsigned int m_IdleTimeout; - DllLibNfs *m_pLibNfs; - void resetContext(); + struct nfs_context *m_pNfsContext;//current nfs context + CStdString m_exportPath;//current connected export path + CStdString m_hostName;//current connected host + CStdString m_resolvedHostName;//current connected host - as ip + size_t m_readChunkSize;//current read chunksize of connected server + size_t m_writeChunkSize;//current write chunksize of connected server + int m_OpenConnections;//number of open connections + unsigned int m_IdleTimeout;//timeout for idle connection close and dyunload + DllLibNfs *m_pLibNfs;//the lib + std::list<CStdString> m_exportList;//list of exported pathes of current connected servers + + void clearMembers(); + bool resetContext();//clear old nfs context and init new context + void resolveHost(const CURL &url);//resolve hostname by dnslookup }; extern CNfsConnection gNfsConnection; diff --git a/xbmc/filesystem/NFSDirectory.cpp b/xbmc/filesystem/NFSDirectory.cpp index b9b3c59f1b..c1a9a723d0 100644 --- a/xbmc/filesystem/NFSDirectory.cpp +++ b/xbmc/filesystem/NFSDirectory.cpp @@ -28,9 +28,9 @@ #include "utils/log.h" #include "utils/URIUtils.h" #include "threads/SingleLock.h" - using namespace XFILE; using namespace std; +#include "nfsc/libnfs-raw-mount.h" CNFSDirectory::CNFSDirectory(void) { @@ -42,44 +42,111 @@ CNFSDirectory::~CNFSDirectory(void) gNfsConnection.AddIdleConnection(); } +bool CNFSDirectory::GetDirectoryFromExportList(const CStdString& strPath, CFileItemList &items) +{ + CURL url(strPath); + CStdString nonConstStrPath(strPath); + std::list<CStdString> exportList=gNfsConnection.GetExportList(url); + std::list<CStdString>::iterator it; + + for(it=exportList.begin();it!=exportList.end();it++) + { + CStdString currentExport(*it); + URIUtils::RemoveSlashAtEnd(nonConstStrPath); + + CFileItemPtr pItem(new CFileItem(currentExport)); + pItem->m_strPath = nonConstStrPath + currentExport; + pItem->m_dateTime=0; + + URIUtils::AddSlashAtEnd(pItem->m_strPath); + pItem->m_bIsFolder = true; + items.Add(pItem); + } + + return exportList.empty()? false : true; +} + +bool CNFSDirectory::GetServerList(CFileItemList &items) +{ + struct nfs_server_list *srvrs; + struct nfs_server_list *srv; + bool ret = false; + + if(!gNfsConnection.HandleDyLoad()) + { + return false; + } + + srvrs = gNfsConnection.GetImpl()->nfs_find_local_servers(); + + for (srv=srvrs; srv; srv = srv->next) + { + CStdString currentExport(srv->addr); + + CFileItemPtr pItem(new CFileItem(currentExport)); + pItem->m_strPath = "nfs://" + currentExport; + pItem->m_dateTime=0; + + URIUtils::AddSlashAtEnd(pItem->m_strPath); + pItem->m_bIsFolder = true; + items.Add(pItem); + ret = true; //added at least one entry + } + gNfsConnection.GetImpl()->free_nfs_srvr_list(srvrs); + + return ret; +} + bool CNFSDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { // We accept nfs://server/path[/file]]]] int ret = 0; FILETIME fileTime, localTime; - CSingleLock lock(gNfsConnection); - + CSingleLock lock(gNfsConnection); CURL url(strPath); - - if(!gNfsConnection.Connect(url)) + CStdString strDirName=""; + + if(!gNfsConnection.Connect(url,strDirName)) { - return false; + //connect has failed - so try to get the exported filesystms if no path is given to the url + if(url.GetShareName().Equals("")) + { + if(url.GetHostName().Equals("")) + { + return GetServerList(items); + } + else + { + return GetDirectoryFromExportList(strPath, items); + } + } + else + { + return false; + } } - - CStdString strDirName="//";//relative to the strPath we connected - we want to get the "/" directory then - + vector<CStdString> vecEntries; struct nfsdir *nfsdir = NULL; struct nfsdirent *nfsdirent = NULL; - ret = gNfsConnection.GetImpl()->nfs_opendir_sync(gNfsConnection.GetNfsContext(), strDirName.c_str(), &nfsdir); - + ret = gNfsConnection.GetImpl()->nfs_opendir(gNfsConnection.GetNfsContext(), strDirName.c_str(), &nfsdir); + if(ret != 0) { CLog::Log(LOGERROR, "Failed to open(%s) %s\n", strDirName.c_str(), gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); return false; } lock.Leave(); - while((nfsdirent = gNfsConnection.GetImpl()->nfs_readdir(gNfsConnection.GetNfsContext(), nfsdir)) != NULL) { vecEntries.push_back(nfsdirent->name); } - + lock.Enter(); gNfsConnection.GetImpl()->nfs_closedir(gNfsConnection.GetNfsContext(), nfsdir);//close the dir lock.Leave(); - + for (size_t i=0; i<vecEntries.size(); i++) { CStdString strName = vecEntries[i]; @@ -95,7 +162,7 @@ bool CNFSDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items CStdString strFullName = strDirName + strName; lock.Enter(); - ret = gNfsConnection.GetImpl()->nfs_stat_sync(gNfsConnection.GetNfsContext(), strFullName.c_str(), &info); + ret = gNfsConnection.GetImpl()->nfs_stat(gNfsConnection.GetNfsContext(), strFullName.c_str(), &info); lock.Leave(); if( ret == 0 ) @@ -108,7 +175,7 @@ bool CNFSDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items } else CLog::Log(LOGERROR, "NFS; Failed to stat(%s) %s\n", strFullName.c_str(), gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); - + LONGLONG ll = Int32x32To64(lTimeDate & 0xffffffff, 10000000) + 116444736000000000ll; fileTime.dwLowDateTime = (DWORD) (ll & 0xffffffff); fileTime.dwHighDateTime = (DWORD)(ll >> 32); @@ -140,15 +207,14 @@ bool CNFSDirectory::Create(const char* strPath) CSingleLock lock(gNfsConnection); CStdString folderName(strPath); - URIUtils::RemoveSlashAtEnd(folderName);//mkdir fails if a slash is at the end!!! - + URIUtils::RemoveSlashAtEnd(folderName);//mkdir fails if a slash is at the end!!! CURL url(folderName); - folderName = "//" + URIUtils::GetFileName(folderName); + folderName = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,folderName)) return false; - ret = gNfsConnection.GetImpl()->nfs_mkdir_sync(gNfsConnection.GetNfsContext(), folderName.c_str()); + ret = gNfsConnection.GetImpl()->nfs_mkdir(gNfsConnection.GetNfsContext(), folderName.c_str()); if(ret != 0) CLog::Log(LOGERROR, "NFS: Failed to create(%s) %s\n", folderName.c_str(), gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); @@ -161,15 +227,14 @@ bool CNFSDirectory::Remove(const char* strPath) CSingleLock lock(gNfsConnection); CStdString folderName(strPath); - URIUtils::RemoveSlashAtEnd(folderName);//rmdir fails if a slash is at the end!!! - + URIUtils::RemoveSlashAtEnd(folderName);//rmdir fails if a slash is at the end!!! CURL url(folderName); - folderName = "//" + URIUtils::GetFileName(folderName); + folderName = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,folderName)) return false; - ret = gNfsConnection.GetImpl()->nfs_rmdir_sync(gNfsConnection.GetNfsContext(), folderName.c_str()); + ret = gNfsConnection.GetImpl()->nfs_rmdir(gNfsConnection.GetNfsContext(), folderName.c_str()); if(ret != 0 && errno != ENOENT) { @@ -186,15 +251,14 @@ bool CNFSDirectory::Exists(const char* strPath) CSingleLock lock(gNfsConnection); CStdString folderName(strPath); URIUtils::RemoveSlashAtEnd(folderName);//remove slash at end or URIUtils::GetFileName won't return what we want... - CURL url(folderName); - folderName = "//" + URIUtils::GetFileName(folderName); + folderName = ""; - if(!gNfsConnection.Connect(url)) + if(!gNfsConnection.Connect(url,folderName)) return false; struct stat info; - ret = gNfsConnection.GetImpl()->nfs_stat_sync(gNfsConnection.GetNfsContext(), folderName.c_str(), &info); + ret = gNfsConnection.GetImpl()->nfs_stat(gNfsConnection.GetNfsContext(), folderName.c_str(), &info); if (ret != 0) { diff --git a/xbmc/filesystem/NFSDirectory.h b/xbmc/filesystem/NFSDirectory.h index aca851bddb..7cce2808e4 100644 --- a/xbmc/filesystem/NFSDirectory.h +++ b/xbmc/filesystem/NFSDirectory.h @@ -27,14 +27,17 @@ namespace XFILE { class CNFSDirectory : public IDirectory { - public: - CNFSDirectory(void); - virtual ~CNFSDirectory(void); - virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); - virtual DIR_CACHE_TYPE GetCacheType(const CStdString &strPath) const { return DIR_CACHE_ONCE; }; - virtual bool Create(const char* strPath); - virtual bool Exists(const char* strPath); - virtual bool Remove(const char* strPath); + public: + CNFSDirectory(void); + virtual ~CNFSDirectory(void); + virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); + virtual DIR_CACHE_TYPE GetCacheType(const CStdString &strPath) const { return DIR_CACHE_ONCE; }; + virtual bool Create(const char* strPath); + virtual bool Exists(const char* strPath); + virtual bool Remove(const char* strPath); + private: + bool GetServerList(CFileItemList &items); + bool GetDirectoryFromExportList(const CStdString& strPath, CFileItemList &items); }; } |