introduce source file when mounting
This commit is contained in:
parent
299c36546e
commit
2345e48cba
10
configure.ac
10
configure.ac
|
@ -16,11 +16,19 @@ AX_CXX_COMPILE_STDCXX_11([noext])
|
|||
AC_CHECK_LIB([mtp], [LIBMTP_Init], [], [AC_MSG_ERROR([libmtp not found])])
|
||||
AC_CHECK_HEADERS([libmtp.h])
|
||||
AC_CHECK_FUNCS([fdatasync])
|
||||
PKG_CHECK_MODULES([FUSE], [fuse >= 2.8])
|
||||
|
||||
PKG_CHECK_MODULES([FUSE], [fuse >= 2.8])
|
||||
AC_SUBST([FUSE_CFLAGS])
|
||||
AC_SUBST([FUSE_LIBS])
|
||||
|
||||
PKG_CHECK_MODULES(
|
||||
[LIBUSB1],
|
||||
[libusb-1.0 >= 1.0.0],
|
||||
[AC_DEFINE([HAVE_LIBUSB1], [], [Have libusb 1.0])]
|
||||
)
|
||||
AC_SUBST([LIBUSB1_CFLAGS])
|
||||
AC_SUBST([LIBUSB1_LIBS])
|
||||
|
||||
AC_OUTPUT([
|
||||
makefile
|
||||
src/makefile
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
bin_PROGRAMS = simple-mtpfs
|
||||
simple_mtpfs_CXXFLAGS = -Wall -pedantic $(FUSE_CFLAGS)
|
||||
simple_mtpfs_CXXFLAGS = -Wall -pedantic $(FUSE_CFLAGS) $(LIBUSB1_CFLAGS)
|
||||
simple_mtpfs_CPPFLAGS = -DFUSE_USE_VERSION=28
|
||||
simple_mtpfs_LDADD = $(MTP_LIBS) $(FUSE_LIBS)
|
||||
simple_mtpfs_LDADD = $(MTP_LIBS) $(FUSE_LIBS) $(LIBUSB1_LIBS)
|
||||
simple_mtpfs_SOURCES = \
|
||||
simple-mtpfs-fuse.h \
|
||||
simple-mtpfs-libmtp.h \
|
||||
|
@ -13,6 +13,7 @@ simple_mtpfs_SOURCES = \
|
|||
simple-mtpfs-type-dir.h \
|
||||
simple-mtpfs-type-file.h \
|
||||
simple-mtpfs-type-tmp-file.h \
|
||||
simple-mtpfs-util.h \
|
||||
simple-mtpfs-fuse.cpp \
|
||||
simple-mtpfs-libmtp.cpp \
|
||||
simple-mtpfs-log.cpp \
|
||||
|
@ -22,4 +23,5 @@ simple_mtpfs_SOURCES = \
|
|||
simple-mtpfs-tmp-files-pool.cpp \
|
||||
simple-mtpfs-type-dir.cpp \
|
||||
simple-mtpfs-type-file.cpp \
|
||||
simple-mtpfs-type-tmp-file.cpp
|
||||
simple-mtpfs-type-tmp-file.cpp \
|
||||
simple-mtpfs-util.cpp
|
||||
|
|
|
@ -31,22 +31,7 @@ extern "C" {
|
|||
}
|
||||
#include "simple-mtpfs-fuse.h"
|
||||
#include "simple-mtpfs-log.h"
|
||||
|
||||
std::string smtpfs_dirname(const std::string &path)
|
||||
{
|
||||
char *str = strdup(path.c_str());
|
||||
std::string result(dirname(str));
|
||||
free(static_cast<void*>(str));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string smtpfs_basename(const std::string &path)
|
||||
{
|
||||
char *str = strdup(path.c_str());
|
||||
std::string result(basename(str));
|
||||
free(static_cast<void*>(str));
|
||||
return result;
|
||||
}
|
||||
#include "simple-mtpfs-util.h"
|
||||
|
||||
int wrap_getattr(const char *path, struct stat *statbuf)
|
||||
{
|
||||
|
@ -179,6 +164,51 @@ int wrap_fgetattr(const char *path, struct stat *buf, struct fuse_file_info *fil
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SMTPFileSystem::SMTPFileSystemOptions::SMTPFileSystemOptions()
|
||||
: m_good(false)
|
||||
, m_help(false)
|
||||
, m_version(false)
|
||||
, m_verbose(false)
|
||||
, m_enable_move(false)
|
||||
, m_list_devices(false)
|
||||
, m_device_no(1)
|
||||
, m_tmp_dir(nullptr)
|
||||
#ifdef HAVE_LIBUSB1
|
||||
, m_device_file(nullptr)
|
||||
, m_mount_point(nullptr)
|
||||
#endif // HAVE_LIBUSB1
|
||||
{
|
||||
}
|
||||
|
||||
SMTPFileSystem::SMTPFileSystemOptions::~SMTPFileSystemOptions()
|
||||
{
|
||||
free(static_cast<void*>(m_tmp_dir));
|
||||
#ifdef HAVE_LIBUSB1
|
||||
free(static_cast<void*>(m_device_file));
|
||||
free(static_cast<void*>(m_mount_point));
|
||||
#endif // HAVE_LIBUSB1
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
int SMTPFileSystem::SMTPFileSystemOptions::opt_proc(void *data, const char *arg, int key,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
SMTPFileSystemOptions *options = static_cast<SMTPFileSystemOptions*>(data);
|
||||
|
||||
if (key == FUSE_OPT_KEY_NONOPT) {
|
||||
if (options->m_mount_point) {
|
||||
options->m_device_file = options->m_mount_point;
|
||||
options->m_mount_point = nullptr;
|
||||
}
|
||||
fuse_opt_add_opt(&options->m_mount_point, arg);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif //HAVE_LIBUSB1
|
||||
|
||||
std::unique_ptr<SMTPFileSystem> SMTPFileSystem::s_instance;
|
||||
|
||||
SMTPFileSystem *SMTPFileSystem::instance()
|
||||
|
@ -243,7 +273,7 @@ bool SMTPFileSystem::parseOptions(int argc, char **argv)
|
|||
|
||||
static struct fuse_opt smtpfs_opts[] = {
|
||||
SMTPFS_OPT_KEY("enable-move", m_enable_move, 1),
|
||||
SMTPFS_OPT_KEY("--device %i", m_device, 0),
|
||||
SMTPFS_OPT_KEY("--device %i", m_device_no, 0),
|
||||
SMTPFS_OPT_KEY("-l", m_list_devices, 1),
|
||||
SMTPFS_OPT_KEY("--list-devices", m_list_devices, 1),
|
||||
SMTPFS_OPT_KEY("-v", m_verbose, 1),
|
||||
|
@ -262,23 +292,32 @@ bool SMTPFileSystem::parseOptions(int argc, char **argv)
|
|||
|
||||
fuse_opt_free_args(&m_args);
|
||||
m_args = FUSE_ARGS_INIT(argc, argv);
|
||||
if (fuse_opt_parse(&m_args, &m_options, smtpfs_opts, nullptr) == -1) {
|
||||
#ifdef HAVE_LIBUSB1
|
||||
fuse_opt_proc_t opt_proc = SMTPFileSystemOptions::opt_proc;
|
||||
#else
|
||||
fuse_opt_proc_t opt_proc = nullptr;
|
||||
#endif // HAVE_LIBUSB1
|
||||
if (fuse_opt_parse(&m_args, &m_options, smtpfs_opts, opt_proc) == -1) {
|
||||
m_options.m_good = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
fuse_opt_add_arg(&m_args, "-s");
|
||||
|
||||
if (m_options.m_version || m_options.m_help || m_options.m_list_devices) {
|
||||
m_options.m_good = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (--m_options.m_device < 0) {
|
||||
if (--m_options.m_device_no < 0) {
|
||||
m_options.m_good = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
if (m_options.m_mount_point)
|
||||
fuse_opt_add_arg(&m_args, m_options.m_mount_point);
|
||||
#endif // HAVE_LIBUSB1
|
||||
fuse_opt_add_arg(&m_args, "-s");
|
||||
|
||||
if (m_options.m_tmp_dir)
|
||||
removeTmpDir();
|
||||
m_options.m_tmp_dir = expandTmpDir(getenv("TMPDIR"));
|
||||
|
@ -298,6 +337,14 @@ bool SMTPFileSystem::parseOptions(int argc, char **argv)
|
|||
fuse_opt_add_arg(&m_args, "-f");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
// device file and -- device are mutually exclusive, fail if both set
|
||||
if (m_options.m_device_no && m_options.m_device_file) {
|
||||
m_options.m_good = false;
|
||||
return false;
|
||||
}
|
||||
#endif // HAVE_LIBUSB1
|
||||
|
||||
m_options.m_good = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -307,7 +354,11 @@ void SMTPFileSystem::printHelp() const
|
|||
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
||||
struct fuse_operations tmp_operations;
|
||||
memset(&tmp_operations, 0, sizeof(tmp_operations));
|
||||
std::cout << "usage: " << m_args.argv[0] << " mountpoint [options]\n\n"
|
||||
std::cout << "usage: " << m_args.argv[0]
|
||||
#ifdef HAVE_LIBUSB1
|
||||
<< " <source>"
|
||||
#endif // HAVE_LIBUSB1
|
||||
<< " mountpoint [options]\n\n"
|
||||
<< "general options:\n"
|
||||
<< " -o opt,[opt...] mount options\n"
|
||||
<< " -h --help print help\n"
|
||||
|
@ -343,8 +394,18 @@ bool SMTPFileSystem::exec()
|
|||
if (m_options.m_version || m_options.m_help)
|
||||
return true;
|
||||
|
||||
if (!m_device.connect(m_options.m_device))
|
||||
return false;
|
||||
#ifdef HAVE_LIBUSB1
|
||||
if (m_options.m_device_file) {
|
||||
// Try to use device file first, if provided
|
||||
if (!m_device.connect(m_options.m_device_file))
|
||||
return false;
|
||||
} else
|
||||
#endif // HAVE_LIBUSB1
|
||||
{
|
||||
// Connect to MTP device by order number, if no device file supplied
|
||||
if (!m_device.connect(m_options.m_device_no))
|
||||
return false;
|
||||
}
|
||||
m_device.enableMove(m_options.m_enable_move);
|
||||
if (fuse_main(m_args.argc, m_args.argv, &m_fuse_operations, nullptr) > 0)
|
||||
return false;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef SMTPFS_FUSE_H
|
||||
#define SMTPFS_FUSE_H
|
||||
|
||||
#include <config.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
@ -45,19 +46,15 @@ private:
|
|||
int m_verbose;
|
||||
int m_enable_move;
|
||||
int m_list_devices;
|
||||
int m_device;
|
||||
int m_device_no;
|
||||
char *m_tmp_dir;
|
||||
#ifdef HAVE_LIBUSB1
|
||||
char *m_device_file;
|
||||
char *m_mount_point;
|
||||
#endif // HAVE_LIBUSB1
|
||||
|
||||
SMTPFileSystemOptions():
|
||||
m_good(false),
|
||||
m_help(false),
|
||||
m_version(false),
|
||||
m_verbose(false),
|
||||
m_enable_move(false),
|
||||
m_list_devices(false),
|
||||
m_device(1),
|
||||
m_tmp_dir(nullptr) {}
|
||||
~SMTPFileSystemOptions() { free(static_cast<void*>(m_tmp_dir)); }
|
||||
SMTPFileSystemOptions();
|
||||
~SMTPFileSystemOptions();
|
||||
|
||||
static int opt_proc(void *data, const char *arg, int key,
|
||||
struct fuse_args *outargs);
|
||||
|
@ -65,6 +62,15 @@ private:
|
|||
|
||||
SMTPFileSystem();
|
||||
|
||||
enum {
|
||||
KEY_ENABLE_MOVE,
|
||||
KEY_DEVICE_NO,
|
||||
KEY_LIST_DEVICES,
|
||||
KEY_VERBOSE,
|
||||
KEY_VERSION,
|
||||
KEY_HELP
|
||||
};
|
||||
|
||||
public:
|
||||
~SMTPFileSystem();
|
||||
|
||||
|
@ -121,7 +127,4 @@ private:
|
|||
MTPDevice m_device;
|
||||
};
|
||||
|
||||
std::string smtpfs_dirname(const std::string &path);
|
||||
std::string smtpfs_basename(const std::string &path);
|
||||
|
||||
#endif // SMTPFS_FUSE_H
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <config.h>
|
||||
#include <iostream>
|
||||
#include "simple-mtpfs-fuse.h"
|
||||
#include "simple-mtpfs-util.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ extern "C" {
|
|||
#include "simple-mtpfs-libmtp.h"
|
||||
#include "simple-mtpfs-log.h"
|
||||
#include "simple-mtpfs-mtp-device.h"
|
||||
#include "simple-mtpfs-util.h"
|
||||
|
||||
uint32_t MTPDevice::s_root_node = ~0;
|
||||
|
||||
|
@ -100,6 +101,33 @@ bool MTPDevice::connect(int dev_no)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
bool MTPDevice::connect(const std::string &dev_file)
|
||||
{
|
||||
if (m_device) {
|
||||
logerr("Already connected.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
LIBMTP_raw_device_t *device = smtpfs_raw_device_new(dev_file);
|
||||
if (!device) {
|
||||
logerr("Could not open such device '", dev_file, ".\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_device = LIBMTP_Open_Raw_Device_Uncached(device);
|
||||
smtpfs_raw_device_free(device);
|
||||
if (!m_device)
|
||||
return false;
|
||||
|
||||
if (!enumStorages())
|
||||
return false;
|
||||
|
||||
logmsg("Connection.\n");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MTPDevice::disconnect()
|
||||
{
|
||||
if (!m_device)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <map>
|
||||
#include <mutex>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
extern "C" {
|
||||
# include <libmtp.h>
|
||||
|
@ -35,6 +36,7 @@ public:
|
|||
~MTPDevice();
|
||||
|
||||
bool connect(int dev_no = 0);
|
||||
bool connect(const std::string &dev_file);
|
||||
void disconnect();
|
||||
|
||||
bool listDevices();
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2012, Peter Hatina <phatina@gmail.com>
|
||||
*
|
||||
* 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 of
|
||||
* the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <config.h>
|
||||
#include <cstring>
|
||||
#ifdef HAVE_LIBUSB1
|
||||
# include <string>
|
||||
# include <iomanip>
|
||||
# include <sstream>
|
||||
#endif // HAVE_LIBUSB1
|
||||
extern "C" {
|
||||
# include <libgen.h>
|
||||
}
|
||||
#ifdef HAVE_LIBUSB1
|
||||
# include <climits>
|
||||
extern "C" {
|
||||
# include <unistd.h>
|
||||
# include <libmtp.h>
|
||||
# include <libusb.h>
|
||||
}
|
||||
#endif // HAVE_LIBUSB1
|
||||
#include "simple-mtpfs-util.h"
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
const char smtpfs_path_delimiter = '/';
|
||||
const std::string smtpfs_devbususb = "/dev/bus/usb/";
|
||||
#endif // HAVE_LIBUSB1
|
||||
|
||||
std::string smtpfs_dirname(const std::string &path)
|
||||
{
|
||||
char *str = strdup(path.c_str());
|
||||
std::string result(dirname(str));
|
||||
free(static_cast<void*>(str));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string smtpfs_basename(const std::string &path)
|
||||
{
|
||||
char *str = strdup(path.c_str());
|
||||
std::string result(basename(str));
|
||||
free(static_cast<void*>(str));
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
std::string smtpfs_realpath(std::string path)
|
||||
{
|
||||
char buf[PATH_MAX + 1];
|
||||
char *real_path = realpath(path.c_str(), buf);
|
||||
return std::string(real_path ? buf : "");
|
||||
}
|
||||
|
||||
LIBMTP_raw_device_t *smtpfs_raw_device_new_priv(libusb_device *usb_device)
|
||||
{
|
||||
if (!usb_device)
|
||||
return nullptr;
|
||||
|
||||
LIBMTP_raw_device_t *device = static_cast<LIBMTP_raw_device_t*>(
|
||||
malloc(sizeof(LIBMTP_raw_device_t)));
|
||||
|
||||
if (!device)
|
||||
return nullptr;
|
||||
|
||||
struct libusb_device_descriptor desc;
|
||||
int err = libusb_get_device_descriptor(usb_device, &desc);
|
||||
if (err != LIBUSB_SUCCESS) {
|
||||
free(static_cast<void*>(device));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
device->device_entry.vendor = nullptr; // TODO: vendor string
|
||||
device->device_entry.vendor_id = desc.idVendor;
|
||||
device->device_entry.product = nullptr; // TODO: product string
|
||||
device->device_entry.product_id = desc.idProduct;
|
||||
device->device_entry.device_flags = 0;
|
||||
|
||||
device->bus_location = static_cast<uint32_t>(libusb_get_bus_number(usb_device));
|
||||
device->devnum = libusb_get_device_address(usb_device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
LIBMTP_raw_device_t *smtpfs_raw_device_new(const std::string &path)
|
||||
{
|
||||
libusb_context *ctx;
|
||||
int err = libusb_init(&ctx);
|
||||
if (err)
|
||||
return nullptr;
|
||||
|
||||
std::string dev_path(smtpfs_realpath(path));
|
||||
libusb_device **dev_list;
|
||||
ssize_t num_devs = libusb_get_device_list(ctx, &dev_list);
|
||||
if (num_devs < 1) {
|
||||
libusb_exit(ctx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
libusb_device *dev = nullptr;
|
||||
for (auto i = 0; i < num_devs; ++i) {
|
||||
dev = dev_list[i];
|
||||
uint8_t bnum = libusb_get_bus_number(dev_list[i]);
|
||||
uint8_t dnum = libusb_get_device_address(dev_list[i]);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << smtpfs_devbususb
|
||||
<< std::setw(3) << std::setfill('0')
|
||||
<< static_cast<uint16_t>(bnum) << "/"
|
||||
<< std::setw(3) << std::setfill('0')
|
||||
<< static_cast<uint16_t>(dnum);
|
||||
|
||||
if (ss.str() == dev_path)
|
||||
break;
|
||||
dev = nullptr;
|
||||
}
|
||||
|
||||
LIBMTP_raw_device_t *raw_device = smtpfs_raw_device_new_priv(dev);
|
||||
|
||||
libusb_free_device_list(dev_list, 0);
|
||||
libusb_exit(ctx);
|
||||
|
||||
return raw_device;
|
||||
}
|
||||
|
||||
void smtpfs_raw_device_free(LIBMTP_raw_device_t *device)
|
||||
{
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
free(static_cast<void*>(device->device_entry.vendor));
|
||||
free(static_cast<void*>(device->device_entry.product));
|
||||
free(static_cast<void*>(device));
|
||||
}
|
||||
#endif // HAVE_LIBUSB1
|
|
@ -0,0 +1,36 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Copyright (C) 2012, Peter Hatina <phatina@gmail.com>
|
||||
*
|
||||
* 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 of
|
||||
* the License, 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef SIMPLE_MTPFS_UTIL
|
||||
#define SIMPLE_MTPFS_UTIL
|
||||
|
||||
#include <config.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
# include <libmtp.h>
|
||||
#endif // HAVE_LIBUSB1
|
||||
|
||||
std::string smtpfs_dirname(const std::string &path);
|
||||
std::string smtpfs_basename(const std::string &path);
|
||||
|
||||
#ifdef HAVE_LIBUSB1
|
||||
LIBMTP_raw_device_t *smtpfs_raw_device_new(const std::string &path);
|
||||
void smtpfs_raw_device_free(LIBMTP_raw_device_t *device);
|
||||
#endif // HAVE_LIBUSB1
|
||||
|
||||
#endif // SIMPLE_MTPFS_UTIL
|
Loading…
Reference in New Issue