aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMemphiz <memphis@machzwo.de>2011-07-18 23:39:27 +0200
committerMemphiz <memphis@machzwo.de>2011-07-18 23:39:27 +0200
commit6713a158ead605d6faf006e4fd1956ae7bbb84c9 (patch)
treebdfab50fc0d22a26293c35d162d728d33277d61a
parent43a13d3bf8eaf49da153a697cb8f0a63f63aba8f (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/Makefile3
-rw-r--r--xbmc/filesystem/FileNFS.cpp257
-rw-r--r--xbmc/filesystem/FileNFS.h56
-rw-r--r--xbmc/filesystem/NFSDirectory.cpp124
-rw-r--r--xbmc/filesystem/NFSDirectory.h19
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);
};
}