Merge pull request #70 from Henneberg-Systemdesign/support-for-get-partial-object

Support for get partial object
This commit is contained in:
Peter Hatina 2019-11-05 21:51:58 +01:00 committed by GitHub
commit c9518f345f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 17 deletions

View File

@ -596,11 +596,19 @@ int SMTPFileSystem::open(const char *path, struct fuse_file_info *file_info)
} else {
tmp_path = m_tmp_files_pool.makeTmpPath(std_path);
int rval = m_device.filePull(std_path, tmp_path);
if (rval != 0)
return -rval;
// only copy the file if needed
if (!hasPartialObjectSupport()) {
int rval = m_device.filePull(std_path, tmp_path);
if (rval != 0)
return -rval;
} else {
int fd = ::creat(tmp_path.c_str(), S_IRUSR | S_IWUSR);
::close(fd);
}
}
// we create the tmp file even if we can use partial get/send to
// have a valid file descriptor
int fd = ::open(tmp_path.c_str(), file_info->flags);
if (fd < 0) {
::unlink(tmp_path.c_str());
@ -620,24 +628,38 @@ int SMTPFileSystem::open(const char *path, struct fuse_file_info *file_info)
int SMTPFileSystem::read(const char *path, char *buf, size_t size,
off_t offset, struct fuse_file_info *file_info)
{
int rval = ::pread(file_info->fh, buf, size, offset);
if (rval < 0)
return -errno;
int rval = 0;
if (hasPartialObjectSupport()) {
const std::string std_path(path);
rval = m_device.fileRead(std_path, buf, size, offset);
} else {
rval = ::pread(file_info->fh, buf, size, offset);
if (rval < 0)
return -errno;
}
return rval;
}
int SMTPFileSystem::write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *file_info)
{
const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(std::string(path));
if (!tmp_file)
return -EINVAL;
int rval = 0;
if (hasPartialObjectSupport()) {
const std::string std_path(path);
rval = m_device.fileWrite(std_path, buf, size, offset);
} else {
const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(std::string(path));
if (!tmp_file)
return -EINVAL;
int rval = ::pwrite(file_info->fh, buf, size, offset);
if (rval < 0)
return -errno;
rval = ::pwrite(file_info->fh, buf, size, offset);
if (rval < 0)
return -errno;
const_cast<TypeTmpFile*>(tmp_file)->setModified();
}
const_cast<TypeTmpFile*>(tmp_file)->setModified();
return rval;
}
@ -764,3 +786,9 @@ int SMTPFileSystem::ftruncate(const char *path, off_t offset,
const_cast<TypeTmpFile*>(tmp_file)->setModified();
return 0;
}
bool SMTPFileSystem::hasPartialObjectSupport()
{
MTPDevice::Capabilities caps = m_device.getCapabilities();
return (caps.canGetPartialObject() && caps.canSendPartialObject());
}

View File

@ -104,10 +104,7 @@ public:
int create(const char *path, mode_t mode, fuse_file_info *file_info);
private:
static bool removeDir(const std::string &dirname);
bool createTmpDir();
bool removeTmpDir();
bool hasPartialObjectSupport();
static std::unique_ptr<SMTPFileSystem> s_instance;
struct fuse_args m_args;

View File

@ -467,6 +467,64 @@ int MTPDevice::rename(const std::string &oldpath, const std::string &newpath)
#endif
}
int MTPDevice::fileRead(const std::string &path, char *buf, size_t size,
off_t offset)
{
const std::string path_basename(smtpfs_basename(path));
const std::string path_dirname(smtpfs_dirname(path));
const TypeDir *dir_parent = dirFetchContent(path_dirname);
const TypeFile *file_to_fetch = dir_parent ?
dir_parent->file(path_basename) : nullptr;
if (!dir_parent) {
logerr("Can not fetch '", path, "'.\n");
return -EINVAL;
}
if (!file_to_fetch) {
logerr("No such file '", path, "'.\n");
return -ENOENT;
}
// all systems clear
unsigned char *tmp_buf;
unsigned int tmp_size;
int rval = LIBMTP_GetPartialObject(m_device, file_to_fetch->id(),
offset, size, &tmp_buf, &tmp_size);
if (tmp_size > 0) {
memcpy(buf, tmp_buf, tmp_size);
free(tmp_buf);
}
if (rval != 0)
return -EIO;
return tmp_size;
}
int MTPDevice::fileWrite(const std::string &path, const char *buf, size_t size,
off_t offset)
{
const std::string path_basename(smtpfs_basename(path));
const std::string path_dirname(smtpfs_dirname(path));
const TypeDir *dir_parent = dirFetchContent(path_dirname);
const TypeFile *file_to_fetch = dir_parent ?
dir_parent->file(path_basename) : nullptr;
if (!dir_parent) {
logerr("Can not fetch '", path, "'.\n");
return -EINVAL;
}
if (!file_to_fetch) {
logerr("No such file '", path, "'.\n");
return -ENOENT;
}
// all systems clear
int rval = LIBMTP_SendPartialObject(m_device, file_to_fetch->id(),
offset, (unsigned char *) buf, size);
if (rval < 0)
return -EIO;
return size;
}
int MTPDevice::filePull(const std::string &src, const std::string &dst)
{
const std::string src_basename(smtpfs_basename(src));

View File

@ -78,6 +78,8 @@ public:
int rename(const std::string &oldpath, const std::string &newpath);
int fileRead(const std::string &path, char *buf, size_t size, off_t offset);
int fileWrite(const std::string &path, const char *buf, size_t size, off_t offset);
int filePull(const std::string &src, const std::string &dst);
int filePush(const std::string &src, const std::string &dst);
int fileRemove(const std::string &path);