ronantakizawa/codereview-bench huggingface dataset:
Repository: xbmc/xbmc
File: xbmc/platform/posix/filesystem/SMBDirectory.cpp (C++)

Code before:
    if (!smb.IsSmbValid())
      return -1;
    fd = smbc_opendir(s.c_str());
  }

  while (fd < 0) /* only to avoid goto in following code */
  {
    std::string cError;

    if (errno == EACCES || errno == EPERM || errno == EAGAIN || errno == EINVAL)
    {
      if (m_flags & DIR_FLAG_ALLOW_PROMPT)
      {
        if (guest) // clean user/pass if tried guest access and failed
        {
          urlIn.SetUserName("");
          urlIn.SetPassword("");
        }
        RequireAuthentication(urlIn);
      }
      break;
    }

    if (errno == ENODEV || errno == ENOENT)
      cError = fmt::format(fmt::runtime(g_localizeStrings.Get(770)), errno);
    else
      cError = strerror(errno);

    if (m_flags & DIR_FLAG_ALLOW_PROMPT)
      SetErrorDialog(257, cError.c_str());
    break;
  }

  if (fd < 0)
  {
    // write error to logfile
    CLog::LogF(LOGERROR, "Unable to open directory : '{}'\nunix_err:'{:x}' error : '{}'",
        CURL::GetRedacted(strAuth), errno, strerror(errno));
  }

  return fd;
}

bool CSMBDirectory::Create(const CURL& url2)
{
  std::unique_lock lock(smb);
  smb.Init();

  CURL url = CSMB::GetResolvedUrl(url2);
  CPasswordManager::GetInstance().AuthenticateURL(url);
  std::string strFileName = smb.URLEncode(url);

Review comment (suggestion):
Direct uses of fmt should also include the fmt header.

```diff
--- a/xbmc/platform/posix/filesystem/SMBDirectory.cpp
+++ b/xbmc/platform/posix/filesystem/SMBDirectory.cpp
@@ -36,6 +36,7 @@

 #include <mutex>

+#include <fmt/format.h>
 #include <libsmbclient.h>

 using namespace XFILE;
```

Code after:
    std::unique_lock lock(smb);
    if (!smb.IsSmbValid())
      return -1;
    fd = smbc_opendir(s.c_str());
  }

  while (fd < 0) /* only to avoid goto in following code */
  {
    std::string cError;

    if (errno == EACCES || errno == EPERM || errno == EAGAIN || errno == EINVAL)
    {
      if (m_flags & DIR_FLAG_ALLOW_PROMPT)
      {
        if (guest) // clean user/pass if tried guest access and failed
        {
          urlIn.SetUserName("");
          urlIn.SetPassword("");
        }
        RequireAuthentication(urlIn);
      }
      break;
    }

    if (errno == ENODEV || errno == ENOENT)
      cError = fmt::format(fmt::runtime(g_localizeStrings.Get(770)), errno);
    else
      cError = strerror(errno);

    if (m_flags & DIR_FLAG_ALLOW_PROMPT)
      SetErrorDialog(257, cError.c_str());
    break;
  }

  if (fd < 0)
  {
    // write error to logfile
    CLog::LogF(LOGERROR, "Unable to open directory : '{}'\nunix_err:'{:x}' error : '{}'",
               CURL::GetRedacted(strAuth), errno, strerror(errno));
  }

  return fd;
}

bool CSMBDirectory::Create(const CURL& url2)
{
  std::unique_lock lock(smb);
  smb.Init();

  CURL url = CSMB::GetResolvedUrl(url2);
  CPasswordManager::GetInstance().AuthenticateURL(url);
Repository: xbmc/xbmc
File: xbmc/platform/posix/filesystem/SMBDirectory.cpp (C++)

Code before:
  if (fd < 0)
    return false;

  URIUtils::AddSlashAtEnd(strRoot);
  URIUtils::AddSlashAtEnd(strAuth);

  lock.lock();
  if (!smb.IsSmbValid())
    return false;

  const libsmb_file_info* fi;
  struct stat st;
  bool atLeastOneEntry = false;
  while ((fi = smbc_readdirplus2(fd, &st)))
  {
    atLeastOneEntry = true;
    // We use UTF-8 internally, as does SMB
    std::string name = fi->name;

    if (name == "." || name == ".." || name == "lost+found")
      continue;

    int64_t size = 0;
    const bool isDir = S_ISDIR(st.st_mode);
    int64_t timeDate = 0;
    bool hidden = name.front() == '.';

    // only stat files that can give proper responses
    if (S_ISREG(st.st_mode) || isDir)
    {
      // This is also present in stuct stat using S_IXOTH but given the potential for confusion
      // let's be explicit.
      hidden = hidden || fi->attrs & SMBC_DOS_MODE_HIDDEN;

      timeDate = st.st_mtime;
      if (timeDate == 0) // if modification date is missing, use create date
        timeDate = st.st_ctime;
      size = st.st_size;
    }

    KODI::TIME::FileTime fileTime, localTime;
    KODI::TIME::TimeTToFileTime(timeDate, &fileTime);
    KODI::TIME::FileTimeToLocalFileTime(&fileTime, &localTime);

    const auto item = std::make_shared<CFileItem>(name);
    item->SetDateTime(localTime);
    if (hidden)
      item->SetProperty("file:hidden", true);
    if (isDir)
    {
      std::string path(strRoot);

Review comment (suggestion):
I would prefer `name.starts_with('.')` as it is save in case `name` is empty for some weird reason.

Code after:
  if (fd < 0)
    return false;

  URIUtils::AddSlashAtEnd(strRoot);
  URIUtils::AddSlashAtEnd(strAuth);

  lock.lock();
  if (!smb.IsSmbValid())
    return false;

  const libsmb_file_info* fi;
  struct stat st;
  bool atLeastOneEntry = false;
  while ((fi = smbc_readdirplus2(fd, &st)))
  {
    atLeastOneEntry = true;
    // We use UTF-8 internally, as does SMB
    std::string name = fi->name;

    if (name == "." || name == ".." || name == "lost+found")
      continue;

    int64_t size = 0;
    const bool isDir = S_ISDIR(st.st_mode);
    int64_t timeDate = 0;
    bool hidden = name.starts_with('.');

    // only stat files that can give proper responses
    if (S_ISREG(st.st_mode) || isDir)
    {
      // This is also present in stuct stat using S_IXOTH but given the potential for confusion
      // let's be explicit.
      hidden = hidden || fi->attrs & SMBC_DOS_MODE_HIDDEN;

      timeDate = st.st_mtime;
      if (timeDate == 0) // if modification date is missing, use create date
        timeDate = st.st_ctime;
      size = st.st_size;
    }

    KODI::TIME::FileTime fileTime, localTime;
    KODI::TIME::TimeTToFileTime(timeDate, &fileTime);
    KODI::TIME::FileTimeToLocalFileTime(&fileTime, &localTime);

    const auto item = std::make_shared<CFileItem>(name);
    item->SetDateTime(localTime);
    if (hidden)
      item->SetProperty("file:hidden", true);
    if (isDir)
    {
      std::string path(strRoot);
Repository: xbmc/xbmc
File: xbmc/utils/URIUtils.h (C/C++)

Code before:
   and returns it.

   This methods goes through the given path and removes any "."
   (as it states "this directory") and resolves any ".." by
   removing the previous directory from the path. This is done
   for file paths and host names (in case of VFS paths).

   \param path Path to be cleaned up
   \return Actual path without any "." or ".."
   */
  static std::string GetRealPath(const std::string &path);

  /*!
   \brief Updates the URL encoded hostname of the given path

   This method must only be used to update paths encoded with
   the old (Eden) URL encoding implementation to the new (Frodo)
   URL encoding implementation (which does not URL encode -_.!().

   \param strFilename Path to update
   \return True if the path has been updated/changed otherwise false
   */
  static bool UpdateUrlEncoding(std::string &strFilename);

  static CURL AddCredentials(const CURL& url);
  static CURL AddCredentials(CURL&& url);

private:
  static std::string resolvePath(const std::string &path);

  /*! \brief Given a path to an .ISO or index.BDMV, returns a bluray:// path.
   \param path the ISO/index.BDMV path.
   \return the bluray:// path.
   */
  static std::string GetBlurayPath(const std::string& path);

  static const CAdvancedSettings* m_advancedSettings;
};



Review comment (security):
out of curiousity. why not only declare the `const CURL&` function and define it like this?
```cpp
CURL URIUtils::AddCredentials(const CURL& url)
{
  CURL authUrl{url};
  if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
    CPasswordManager::GetInstance().AuthenticateURL(authUrl);

  return authUrl;
}
```
should be the same when we never call `URIUtils::AddCredentials(std::move(something));` anywhere or directly with a temporary


Code after:
   and returns it.

   This methods goes through the given path and removes any "."
   (as it states "this directory") and resolves any ".." by
   removing the previous directory from the path. This is done
   for file paths and host names (in case of VFS paths).

   \param path Path to be cleaned up
   \return Actual path without any "." or ".."
   */
  static std::string GetRealPath(const std::string &path);

  /*!
   \brief Updates the URL encoded hostname of the given path

   This method must only be used to update paths encoded with
   the old (Eden) URL encoding implementation to the new (Frodo)
   URL encoding implementation (which does not URL encode -_.!().

   \param strFilename Path to update
   \return True if the path has been updated/changed otherwise false
   */
  static bool UpdateUrlEncoding(std::string &strFilename);

  static CURL AddCredentials(CURL url);

private:
  static std::string resolvePath(const std::string &path);

  /*! \brief Given a path to an .ISO or index.BDMV, returns a bluray:// path.
   \param path the ISO/index.BDMV path.
   \return the bluray:// path.
   */
  static std::string GetBlurayPath(const std::string& path);

  static const CAdvancedSettings* m_advancedSettings;
};
Repository: xbmc/xbmc
File: xbmc/utils/URIUtils.cpp (C++)

Code before:
    url.Parse(stackPath);
  }
  // if the protocol has an encoded hostname we need to work with its hostname
  else if (URIUtils::HasEncodedHostname(url))
  {
    std::string hostname = url.GetHostName();
    UpdateUrlEncoding(hostname);
    url.SetHostName(hostname);
  }
  else
    return false;

  std::string newFilename = url.Get();
  if (newFilename == strFilename)
    return false;

  strFilename = newFilename;
  return true;
}

CURL URIUtils::AddCredentials(const CURL& url)
{
  return AddCredentials(CURL(url));
}

CURL URIUtils::AddCredentials(CURL&& authUrl)
{
  if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
    CPasswordManager::GetInstance().AuthenticateURL(authUrl);
  return authUrl;
}


Review comment (security):
One single function can handle both cases:
```cpp
CURL URIUtils::AddCredentials(CURL authUrl)
{
  if (CPasswordManager::GetInstance().IsURLSupported(authUrl) && authUrl.GetUserName().empty())
    CPasswordManager::GetInstance().AuthenticateURL(authUrl);
  return authUrl;
}
```

Code after:
    url.Parse(stackPath);
  }
  // if the protocol has an encoded hostname we need to work with its hostname
  else if (URIUtils::HasEncodedHostname(url))
  {
    std::string hostname = url.GetHostName();
    UpdateUrlEncoding(hostname);
    url.SetHostName(hostname);
  }
  else
    return false;

  std::string newFilename = url.Get();
  if (newFilename == strFilename)
    return false;

  strFilename = newFilename;
  return true;
}

CURL URIUtils::AddCredentials(CURL url)
{
  if (CPasswordManager::GetInstance().IsURLSupported(url) && url.GetUserName().empty())
    CPasswordManager::GetInstance().AuthenticateURL(url);
  return url;
}
Repository: xbmc/xbmc
File: xbmc/URL.cpp (C++)

Code before:
#include <system_error>
#include <vector>

#include <fmt/xchar.h>

using namespace ADDON;

CURL::~CURL() = default;

void CURL::Reset()
{
  m_strHostName.clear();
  m_strDomain.clear();
  m_strUserName.clear();
  m_strPassword.clear();
  m_strShareName.clear();
  m_strFileName.clear();
  m_strProtocol.clear();
  m_strFileType.clear();
  m_strOptions.clear();
  m_strProtocolOptions.clear();
  m_options.Clear();
  m_protocolOptions.Clear();
  m_iPort = 0;
}

void CURL::Parse(std::string strURL1)
{
  Reset();
  // start by validating the path
  std::string strURL = CUtil::ValidatePath(std::move(strURL1));

  // strURL can be one of the following:
  // format 1: protocol://[username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file
  // format 3: drive:directoryandfile
  //
  // first need 2 check if this is a protocol or just a normal drive & path
  if (strURL.empty())
    return;
  if (strURL == "?") return;

  // form is format 1 or 2
  // format 1: protocol://[domain;][username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file

  // decode protocol
  size_t iPos = strURL.find("://");
  if (iPos == std::string::npos)
  {
    // This is an ugly hack that needs some work.

Review comment (suggestion):
nice cleanup of legacy code, thanks. i'd just move those definitions into the header. +1 for adding tests

Code after:
#include <system_error>
#include <vector>

#include <fmt/xchar.h>

using namespace ADDON;

CURL::CURL(std::string strURL)
{
  Parse(std::move(strURL));
}

bool CURL::operator==(const CURL& url) const
{
  return url == Get();
}

bool operator==(const CURL& url, const std::string& str)
{
  return url.Get() == str;
}

bool operator==(const std::string& str, const CURL& url)
{
  return url == str;
}

void CURL::Reset()
{
  m_strHostName.clear();
  m_strDomain.clear();
  m_strUserName.clear();
  m_strPassword.clear();
  m_strShareName.clear();
  m_strFileName.clear();
  m_strProtocol.clear();
  m_strFileType.clear();
  m_strOptions.clear();
  m_strProtocolOptions.clear();
  m_options.Clear();
  m_protocolOptions.Clear();
  m_iPort = 0;
}

void CURL::Parse(std::string strURL1)
{
  Reset();
  // start by validating the path
  std::string strURL = CUtil::ValidatePath(std::move(strURL1));

  // strURL can be one of the following:
Repository: xbmc/xbmc
File: xbmc/URL.cpp (C++)

Code before:
#include <system_error>
#include <vector>

#include <fmt/xchar.h>

using namespace ADDON;

CURL::~CURL() = default;

void CURL::Reset()
{
  m_strHostName.clear();
  m_strDomain.clear();
  m_strUserName.clear();
  m_strPassword.clear();
  m_strShareName.clear();
  m_strFileName.clear();
  m_strProtocol.clear();
  m_strFileType.clear();
  m_strOptions.clear();
  m_strProtocolOptions.clear();
  m_options.Clear();
  m_protocolOptions.Clear();
  m_iPort = 0;
}

void CURL::Parse(std::string strURL1)
{
  Reset();
  // start by validating the path
  std::string strURL = CUtil::ValidatePath(std::move(strURL1));

  // strURL can be one of the following:
  // format 1: protocol://[username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file
  // format 3: drive:directoryandfile
  //
  // first need 2 check if this is a protocol or just a normal drive & path
  if (strURL.empty())
    return;
  if (strURL == "?") return;

  // form is format 1 or 2
  // format 1: protocol://[domain;][username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file

  // decode protocol
  size_t iPos = strURL.find("://");
  if (iPos == std::string::npos)
  {
    // This is an ugly hack that needs some work.

Review comment (bug):
something looks wrong to me here. both `operator==` are the same (only parameters order is swapped) but the return statements differ.
```
return url.Get() == str;
return url == str;
```

Code after:
#include <system_error>
#include <vector>

#include <fmt/xchar.h>

using namespace ADDON;

CURL::CURL(std::string strURL)
{
  Parse(std::move(strURL));
}

bool CURL::operator==(const CURL& url) const
{
  return url == Get();
}

bool operator==(const CURL& url, const std::string& str)
{
  return url.Get() == str;
}

bool operator==(const std::string& str, const CURL& url)
{
  return url == str;
}

void CURL::Reset()
{
  m_strHostName.clear();
  m_strDomain.clear();
  m_strUserName.clear();
  m_strPassword.clear();
  m_strShareName.clear();
  m_strFileName.clear();
  m_strProtocol.clear();
  m_strFileType.clear();
  m_strOptions.clear();
  m_strProtocolOptions.clear();
  m_options.Clear();
  m_protocolOptions.Clear();
  m_iPort = 0;
}

void CURL::Parse(std::string strURL1)
{
  Reset();
  // start by validating the path
  std::string strURL = CUtil::ValidatePath(std::move(strURL1));

  // strURL can be one of the following:
Repository: xbmc/xbmc
File: xbmc/windowing/gbm/WinSystemGbmEGLContext.cpp (C++)

Code before:
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "WinSystemGbmEGLContext.h"

#include "OptionalsReg.h"
#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
#include "drm/DRMAtomic.h"
#include "utils/log.h"

using namespace KODI::WINDOWING::GBM;
using namespace KODI::WINDOWING::LINUX;

bool CWinSystemGbmEGLContext::InitWindowSystemEGL(EGLint renderableType, EGLint apiType)
{
  if (!CWinSystemGbm::InitWindowSystem())
  {
    return false;
  }

  if (!m_eglContext.CreatePlatformDisplay(m_GBM->GetDevice().Get(), m_GBM->GetDevice().Get()))
  {
    return false;
  }

  if (!m_eglContext.InitializeDisplay(apiType))
  {
    return false;
  }

  auto plane = m_DRM->GetGuiPlane();
  uint32_t visualId = plane != nullptr ? plane->GetFormat() : DRM_FORMAT_XRGB2101010;


Review comment (refactor):
This breaks the abstraction.

It would be nice if we could check the next layer up `if (supportsFences())` in CWinSystemGbm which then calls into CDRMUtils of the same call. The atomic and legacy version can then provide overrides if they support using fences or not.

Code after:
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "WinSystemGbmEGLContext.h"

#include "OptionalsReg.h"
#include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
#include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
#include "utils/log.h"

using namespace KODI::WINDOWING::GBM;
using namespace KODI::WINDOWING::LINUX;

bool CWinSystemGbmEGLContext::InitWindowSystemEGL(EGLint renderableType, EGLint apiType)
{
  if (!CWinSystemGbm::InitWindowSystem())
  {
    return false;
  }

  if (!m_eglContext.CreatePlatformDisplay(m_GBM->GetDevice().Get(), m_GBM->GetDevice().Get()))
  {
    return false;
  }

  if (!m_eglContext.InitializeDisplay(apiType))
  {
    return false;
  }

  auto plane = m_DRM->GetGuiPlane();
  uint32_t visualId = plane != nullptr ? plane->GetFormat() : DRM_FORMAT_XRGB2101010;

  // prefer alpha visual id, fallback to non-alpha visual id
Repository: xbmc/xbmc
File: xbmc/filesystem/NFSDirectory.h (C/C++)

Code before:
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "FileItem.h"
#include "FileItemList.h"
#include "IDirectory.h"
#include "NFSFile.h"

#include <vector>

struct nfsdirent;

namespace XFILE
{
  class CNFSDirectory : public IDirectory
  {
    public:
      CNFSDirectory(void);
      ~CNFSDirectory(void) override;
      bool GetDirectory(const CURL& url, CFileItemList &items) override;
      CacheType GetCacheType(const CURL& url) const override { return CacheType::ONCE; }
      bool Create(const CURL& url) override;
      bool Exists(const CURL& url) override;
      bool Remove(const CURL& url) override;
    private:
      std::vector<CFileItemPtr> GetServerList();
      std::vector<CFileItemPtr> GetDirectoryFromExportList(const CURL& inputURL);
      bool ResolveSymlink(const std::string& dirName,
                          struct nfsdirent* dirent,
                          std::string& resolvedPath);

Review comment (suggestion):
FileItem.h actually needs not to be included in this header file.

For `CFileItemPtr` use the native type instead of the typedef from FileItem.h . Include `<memory>`, put `class CFileItem;` in this header and replace `CFileItemPtr` occurrences with `std::shared_ptr<CFileItem>`.

Code after:
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "IDirectory.h"
#include "NFSFile.h"

#include <memory>
#include <vector>

class CFileItem;
struct nfsdirent;

namespace XFILE
{
  class CNFSDirectory : public IDirectory
  {
    public:
      CNFSDirectory(void);
      ~CNFSDirectory(void) override;
      bool GetDirectory(const CURL& url, CFileItemList &items) override;
      CacheType GetCacheType(const CURL& url) const override { return CacheType::ONCE; }
      bool Create(const CURL& url) override;
      bool Exists(const CURL& url) override;
      bool Remove(const CURL& url) override;
    private:
      std::vector<std::shared_ptr<CFileItem>> GetServerList();
      std::vector<std::shared_ptr<CFileItem>> GetDirectoryFromExportList(const CURL& inputURL);
      bool ResolveSymlink(const std::string& dirName,
                          struct nfsdirent* dirent,
                          std::string& resolvedPath);
Repository: xbmc/xbmc
File: xbmc/filesystem/NFSDirectory.h (C/C++)

Code before:
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "IDirectory.h"
#include "NFSFile.h"

#include <memory>
#include <vector>

class CFileItem;
class CFileItemList;
struct nfsdirent;

namespace XFILE
{
  class CNFSDirectory : public IDirectory
  {
    public:
      CNFSDirectory(void);
      ~CNFSDirectory(void) override;
      bool GetDirectory(const CURL& url, CFileItemList &items) override;
      CacheType GetCacheType(const CURL& url) const override { return CacheType::ONCE; }
      bool Create(const CURL& url) override;
      bool Exists(const CURL& url) override;
      bool Remove(const CURL& url) override;
    private:
      std::vector<std::shared_ptr<CFileItem>> GetServerList();
      std::vector<std::shared_ptr<CFileItem>> GetDirectoryFromExportList(const CURL& inputURL);
      bool ResolveSymlink(const std::string& dirName,
                          struct nfsdirent* dirent,
                          std::string& resolvedPath);
  };
}



Review comment (performance):
There is this method defined in the header:

```c++
CacheType GetCacheType(const CURL& url) const override { return CacheType::ONCE; }
```

 For `CacheType::ONCE` you need to include `CFileItemList.h`, where this value is defined. 
 Alternatively, you could outline the implementation.

Code after:
/*
 *  Copyright (C) 2011-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "IDirectory.h"
#include "NFSFile.h"

#include <memory>
#include <vector>

class CFileItem;
struct nfsdirent;

namespace XFILE
{
  class CNFSDirectory : public IDirectory
  {
    public:
      CNFSDirectory(void);
      ~CNFSDirectory(void) override;
      bool GetDirectory(const CURL& url, CFileItemList &items) override;
      CacheType GetCacheType(const CURL& url) const override { return CacheType::ONCE; }
      bool Create(const CURL& url) override;
      bool Exists(const CURL& url) override;
      bool Remove(const CURL& url) override;
    private:
      std::vector<std::shared_ptr<CFileItem>> GetServerList();
      std::vector<std::shared_ptr<CFileItem>> GetDirectoryFromExportList(const CURL& inputURL);
      bool ResolveSymlink(const std::string& dirName,
                          struct nfsdirent* dirent,
                          std::string& resolvedPath);
  };
}