Skip to content

Commit

Permalink
Added support for get/sendPartialObject
Browse files Browse the repository at this point in the history
If the caps flags are enabled for both get and send of partial object
this method is used instead of file push and pull. This makes many file
operations much faster and is widely supported throughout mobile
devices.

We still use the tmp file, not for storing data but to keep a unique
file handler for all the fuse file operations.

No caching happens at the moment, we could cache in the tmp file and
keep a table of offsets and sizes of the file that we already cached,
however, using the kernel file system cache is much better.
  • Loading branch information
jh-hsd committed Nov 2, 2019
1 parent e121556 commit 2bcc455
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 13 deletions.
54 changes: 41 additions & 13 deletions src/simple-mtpfs-fuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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;
}

Expand Down Expand Up @@ -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());
}
1 change: 1 addition & 0 deletions src/simple-mtpfs-fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class SMTPFileSystem
int create(const char *path, mode_t mode, fuse_file_info *file_info);

private:
bool hasPartialObjectSupport();

static std::unique_ptr<SMTPFileSystem> s_instance;
struct fuse_args m_args;
Expand Down
58 changes: 58 additions & 0 deletions src/simple-mtpfs-mtp-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 2 additions & 0 deletions src/simple-mtpfs-mtp-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class MTPDevice

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);
Expand Down

0 comments on commit 2bcc455

Please sign in to comment.