introduce source file when mounting

This commit is contained in:
Peter Hatina 2013-09-17 21:43:36 +02:00
parent 299c36546e
commit 2345e48cba
9 changed files with 330 additions and 42 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)
{

View File

@ -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)

View File

@ -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();

147
src/simple-mtpfs-util.cpp Normal file
View File

@ -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

36
src/simple-mtpfs-util.h Normal file
View File

@ -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