Skip to content

Commit

Permalink
Merge pull request xbmc#18197 from AlwinEsch/change-vfs2
Browse files Browse the repository at this point in the history
[addons][vfs] cleanup API, improve "C" interface, not use void* direct as value
  • Loading branch information
AlwinEsch authored Sep 15, 2020
2 parents afac769 + 7d96fca commit e8d7e6e
Show file tree
Hide file tree
Showing 11 changed files with 696 additions and 472 deletions.
176 changes: 100 additions & 76 deletions xbmc/addons/VFSEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,30 @@
#include "utils/StringUtils.h"
#include "utils/log.h"

#if defined(TARGET_WINDOWS)
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_IFBLK
#define S_IFBLK 0
#endif
#ifndef S_IFSOCK
#define S_IFSOCK 0
#endif
#ifndef S_IFREG
#define S_IFREG _S_IFREG
#endif
#ifndef S_IFCHR
#define S_IFCHR _S_IFCHR
#endif
#ifndef S_IFDIR
#define S_IFDIR _S_IFDIR
#endif
#ifndef S_IFIFO
#define S_IFIFO _S_IFIFO
#endif
#endif

namespace ADDON
{

Expand Down Expand Up @@ -249,27 +273,53 @@ bool CVFSEntry::Exists(const CURL& url)

int CVFSEntry::Stat(const CURL& url, struct __stat64* buffer)
{
int ret = -1;
if (!m_struct.toAddon->stat)
return -1;
return ret;

CVFSURLWrapper url2(url);
return m_struct.toAddon->stat(&m_struct, &url2.url, buffer);
STAT_STRUCTURE statBuffer = {};
ret = m_struct.toAddon->stat(&m_struct, &url2.url, &statBuffer);

buffer->st_dev = statBuffer.deviceId;
buffer->st_ino = statBuffer.fileSerialNumber;
buffer->st_size = statBuffer.size;
buffer->st_atime = statBuffer.accessTime;
buffer->st_mtime = statBuffer.modificationTime;
buffer->st_ctime = statBuffer.statusTime;
buffer->st_mode = 0;
if (statBuffer.isDirectory)
buffer->st_mode |= S_IFDIR;
if (statBuffer.isSymLink)
buffer->st_mode |= S_IFLNK;
if (statBuffer.isBlock)
buffer->st_mode |= S_IFBLK;
if (statBuffer.isCharacter)
buffer->st_mode |= S_IFCHR;
if (statBuffer.isFifo)
buffer->st_mode |= S_IFIFO;
if (statBuffer.isRegular)
buffer->st_mode |= S_IFREG;
if (statBuffer.isSocket)
buffer->st_mode |= S_IFSOCK;

return ret;
}

ssize_t CVFSEntry::Read(void* ctx, void* lpBuf, size_t uiBufSize)
{
if (!m_struct.toAddon->read)
return 0;

return m_struct.toAddon->read(&m_struct, ctx, lpBuf, uiBufSize);
return m_struct.toAddon->read(&m_struct, ctx, static_cast<uint8_t*>(lpBuf), uiBufSize);
}

ssize_t CVFSEntry::Write(void* ctx, const void* lpBuf, size_t uiBufSize)
{
if (!m_struct.toAddon->write)
return 0;

return m_struct.toAddon->write(&m_struct, ctx, lpBuf, uiBufSize);
return m_struct.toAddon->write(&m_struct, ctx, static_cast<const uint8_t*>(lpBuf), uiBufSize);
}

int64_t CVFSEntry::Seek(void* ctx, int64_t position, int whence)
Expand Down Expand Up @@ -320,47 +370,59 @@ int64_t CVFSEntry::GetLength(void* ctx)

int CVFSEntry::IoControl(void* ctx, XFILE::EIoControl request, void* param)
{
if (!m_struct.toAddon->io_control)
return -1;

VFS_IOCTRL ctrl = TranslateIOCTRLToAddon(request);
if (ctrl == VFS_IOCTRL_INVALID)
return -1;

/*! @note @ref VFS_IOCTRL_NATIVE a call to addon to give data! */
if (ctrl == VFS_IOCTRL_NATIVE)
switch (request)
{
XFILE::SNativeIoControl* kodiData = static_cast<XFILE::SNativeIoControl*>(param);
if (!kodiData)
return -1;

VFS_IOCTRL_NATIVE_DATA data;
data.request = kodiData->request;
data.param = kodiData->param;
return m_struct.toAddon->io_control(&m_struct, ctx, ctrl, &data);
}
case XFILE::EIoControl::IOCTRL_SEEK_POSSIBLE:
{
if (!m_struct.toAddon->io_control_get_seek_possible)
return -1;
return m_struct.toAddon->io_control_get_seek_possible(&m_struct, ctx) ? 1 : 0;
}
case XFILE::EIoControl::IOCTRL_CACHE_STATUS:
{
if (!m_struct.toAddon->io_control_get_cache_status)
return -1;

/*! @note @ref VFS_IOCTRL_CACHE_STATUS a call to addon to become data from him! */
if (ctrl == VFS_IOCTRL_CACHE_STATUS)
{
XFILE::SCacheStatus* kodiData = static_cast<XFILE::SCacheStatus*>(param);
if (!kodiData)
return -1;
XFILE::SCacheStatus* kodiData = static_cast<XFILE::SCacheStatus*>(param);
if (!kodiData)
return -1;

VFS_IOCTRL_CACHE_STATUS_DATA data = {0};
int ret = m_struct.toAddon->io_control(&m_struct, ctx, ctrl, &data);
if (ret >= 0)
VFS_CACHE_STATUS_DATA status;
int ret = m_struct.toAddon->io_control_get_cache_status(&m_struct, ctx, &status) ? 0 : -1;
if (ret >= 0)
{
kodiData->forward = status.forward;
kodiData->maxrate = status.maxrate;
kodiData->currate = status.currate;
kodiData->lowspeed = status.lowspeed;
}
return ret;
}
case XFILE::EIoControl::IOCTRL_CACHE_SETRATE:
{
kodiData->forward = data.forward;
kodiData->maxrate = data.maxrate;
kodiData->currate = data.currate;
kodiData->lowspeed = data.lowspeed;
if (!m_struct.toAddon->io_control_set_cache_rate)
return -1;

unsigned int& iParam = *static_cast<unsigned int*>(param);
return m_struct.toAddon->io_control_set_cache_rate(&m_struct, ctx, iParam) ? 1 : 0;
}
return ret;
case XFILE::EIoControl::IOCTRL_SET_RETRY:
{
if (!m_struct.toAddon->io_control_set_retry)
return -1;

bool& bParam = *static_cast<bool*>(param);
return m_struct.toAddon->io_control_set_retry(&m_struct, ctx, bParam) ? 0 : -1;
}

// Not by addon supported io's
case XFILE::EIoControl::IOCTRL_SET_CACHE:
case XFILE::EIoControl::IOCTRL_NATIVE:
default:
break;
}

/*! Do the rest for IoControl, the "param" should normally "nullptr" for this. */
return m_struct.toAddon->io_control(&m_struct, ctx, ctrl, param);
return -1;
}

bool CVFSEntry::Delete(const CURL& url)
Expand Down Expand Up @@ -501,44 +563,6 @@ bool CVFSEntry::ContainsFiles(const CURL& url, CFileItemList& items)
return true;
}

int CVFSEntry::TranslateIOCTRLToKodi(VFS_IOCTRL ioctrl)
{
switch(ioctrl)
{
case VFS_IOCTRL_NATIVE:
return XFILE::EIoControl::IOCTRL_NATIVE;
case VFS_IOCTRL_SEEK_POSSIBLE:
return XFILE::EIoControl::IOCTRL_SEEK_POSSIBLE;
case VFS_IOCTRL_CACHE_STATUS:
return XFILE::EIoControl::IOCTRL_CACHE_STATUS;
case VFS_IOCTRL_CACHE_SETRATE:
return XFILE::EIoControl::IOCTRL_CACHE_SETRATE;
case VFS_IOCTRL_SET_RETRY:
return XFILE::EIoControl::IOCTRL_SET_RETRY;
default:
return XFILE::EIoControl::IOCTRL_INVALID;
}
}

VFS_IOCTRL CVFSEntry::TranslateIOCTRLToAddon(int ioctrl)
{
switch(ioctrl)
{
case XFILE::EIoControl::IOCTRL_NATIVE:
return VFS_IOCTRL_NATIVE;
case XFILE::EIoControl::IOCTRL_SEEK_POSSIBLE:
return VFS_IOCTRL_SEEK_POSSIBLE;
case XFILE::EIoControl::IOCTRL_CACHE_STATUS:
return VFS_IOCTRL_CACHE_STATUS;
case XFILE::EIoControl::IOCTRL_CACHE_SETRATE:
return VFS_IOCTRL_CACHE_SETRATE;
case XFILE::EIoControl::IOCTRL_SET_RETRY:
return VFS_IOCTRL_SET_RETRY;
default:
return VFS_IOCTRL_INVALID;
}
}

CVFSEntryIFileWrapper::CVFSEntryIFileWrapper(VFSEntryPtr ptr) :
m_context(nullptr), m_addon(ptr)
{
Expand Down
12 changes: 0 additions & 12 deletions xbmc/addons/VFSEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,6 @@ namespace ADDON
const std::string& GetZeroconfType() const { return m_zeroconf; }
const ProtocolInfo& GetProtocolInfo() const { return m_protocolInfo; }
protected:
/*!
* @brief TO translate `enum XFILE::EIoControl` to/from `enum VFS_IOCTRL`.
*
* This is meant to interact securely between Kodi and addon.
*
* @note The `int` there is `enum XFILE::EIoControl`
*/
//@{
static int TranslateIOCTRLToKodi(VFS_IOCTRL ioctrl);
static VFS_IOCTRL TranslateIOCTRLToAddon(int ioctrl);
//@}

std::string m_protocols; //!< Protocols for VFS entry.
std::string m_extensions; //!< Extensions for VFS entry.
std::string m_zeroconf; //!< Zero conf announce string for VFS protocol.
Expand Down
46 changes: 43 additions & 3 deletions xbmc/addons/interfaces/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,31 @@

#include <vector>

#ifndef S_ISDIR
#define S_ISDIR(mode) ((((mode)) & 0170000) == (0040000))
#if defined(TARGET_WINDOWS)
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
#ifndef S_ISBLK
#define S_ISBLK(m) (0)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(m) (0)
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) ((((mode)) & 0170000) == (0120000))
#define S_ISLNK(m) ((m & S_IFLNK) != 0)
#endif
#ifndef S_ISCHR
#define S_ISCHR(m) ((m & _S_IFCHR) != 0)
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) ((m & _S_IFDIR) != 0)
#endif
#ifndef S_ISFIFO
#define S_ISFIFO(m) ((m & _S_IFIFO) != 0)
#endif
#ifndef S_ISREG
#define S_ISREG(m) ((m & _S_IFREG) != 0)
#endif
#endif

using namespace kodi; // addon-dev-kit namespace
Expand All @@ -46,6 +66,7 @@ void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface)
addonInterface->toKodi->kodi_filesystem->create_directory = create_directory;
addonInterface->toKodi->kodi_filesystem->directory_exists = directory_exists;
addonInterface->toKodi->kodi_filesystem->remove_directory = remove_directory;
addonInterface->toKodi->kodi_filesystem->remove_directory_recursive = remove_directory_recursive;
addonInterface->toKodi->kodi_filesystem->get_directory = get_directory;
addonInterface->toKodi->kodi_filesystem->free_directory = free_directory;

Expand Down Expand Up @@ -193,6 +214,19 @@ bool Interface_Filesystem::remove_directory(void* kodiBase, const char* path)
return CDirectory::Remove(path);
}

bool Interface_Filesystem::remove_directory_recursive(void* kodiBase, const char* path)
{
CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
if (addon == nullptr || path == nullptr)
{
CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}')",
__FUNCTION__, kodiBase, static_cast<const void*>(path));
return false;
}

return CDirectory::RemoveRecursive(path);
}

static void CFileItemListToVFSDirEntries(VFSDirEntry* entries, const CFileItemList& items)
{
for (unsigned int i = 0; i < static_cast<unsigned int>(items.Size()); ++i)
Expand Down Expand Up @@ -297,12 +331,18 @@ bool Interface_Filesystem::stat_file(void* kodiBase,
return false;

buffer->deviceId = statBuffer.st_dev;
buffer->fileSerialNumber = statBuffer.st_ino;
buffer->size = statBuffer.st_size;
buffer->accessTime = statBuffer.st_atime;
buffer->modificationTime = statBuffer.st_mtime;
buffer->statusTime = statBuffer.st_ctime;
buffer->isDirectory = S_ISDIR(statBuffer.st_mode);
buffer->isSymLink = S_ISLNK(statBuffer.st_mode);
buffer->isBlock = S_ISBLK(statBuffer.st_mode);
buffer->isCharacter = S_ISCHR(statBuffer.st_mode);
buffer->isFifo = S_ISFIFO(statBuffer.st_mode);
buffer->isRegular = S_ISREG(statBuffer.st_mode);
buffer->isSocket = S_ISSOCK(statBuffer.st_mode);

return true;
}
Expand Down
1 change: 1 addition & 0 deletions xbmc/addons/interfaces/Filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct Interface_Filesystem
static bool create_directory(void* kodiBase, const char* path);
static bool directory_exists(void* kodiBase, const char* path);
static bool remove_directory(void* kodiBase, const char* path);
static bool remove_directory_recursive(void* kodiBase, const char* path);
static bool get_directory(void* kodiBase,
const char* path,
const char* mask,
Expand Down
Loading

0 comments on commit e8d7e6e

Please sign in to comment.