Use the user that started jmtpfs for the uid and gid of the files.

Return total for all storage devices for statfs of the root directory.
This commit is contained in:
Jason Ferrara 2012-05-11 03:57:07 +00:00
parent 71283756a1
commit 385417b93c
14 changed files with 283 additions and 70 deletions

View File

@ -56,6 +56,22 @@ MtpLibLock lock;
return std::unique_ptr<MtpDevice>(new MtpDevice(m_devs[index]));
}
std::unique_ptr<MtpDevice> ConnectedMtpDevices::GetDevice(uint32_t busLocation, uint8_t devnum)
{
MtpLibLock lock;
for(int i = 0; i<NumDevices(); i++)
{
ConnectedDeviceInfo devInfo = GetDeviceInfo(i);
if ((devInfo.bus_location == busLocation) &&
(devInfo.devnum == devnum))
{
return GetDevice(i);;
}
}
throw MtpDeviceNotFound("Requested MTP device not found");
}
LIBMTP_raw_device_t& ConnectedMtpDevices::GetRawDeviceEntry(int index)
{
return m_devs[index];

View File

@ -43,6 +43,8 @@ public:
int NumDevices();
std::unique_ptr<MtpDevice> GetDevice(int index);
std::unique_ptr<MtpDevice> GetDevice(uint32_t busLocation, uint8_t devnum);
ConnectedDeviceInfo GetDeviceInfo(int index);
LIBMTP_raw_device_t& GetRawDeviceEntry(int index);

View File

@ -1,6 +1,7 @@
bin_PROGRAMS=jmtpfs
jmtpfs_SOURCES=jmtpfs.cpp MtpDevice.cpp ConnectedMtpDevices.cpp Mutex.cpp MtpFilesystemPath.cpp \
MtpMetadataCache.cpp MtpNode.cpp MtpRoot.cpp MtpLibLock.cpp MtpStorage.cpp \
MtpFolder.cpp MtpFile.cpp TemporaryFile.cpp MtpLocalFileCopy.cpp
MtpFolder.cpp MtpFile.cpp TemporaryFile.cpp MtpLocalFileCopy.cpp \
MtpFuseContext.cpp
jmtpfs_CPPFLAGS = $(MTP_CFLAGS) $(FUSE_CFLAGS)
jmtpfs_LDADD = $(MTP_LIBS) $(FUSE_LIBS)

View File

@ -54,7 +54,8 @@ am_jmtpfs_OBJECTS = jmtpfs-jmtpfs.$(OBJEXT) jmtpfs-MtpDevice.$(OBJEXT) \
jmtpfs-MtpRoot.$(OBJEXT) jmtpfs-MtpLibLock.$(OBJEXT) \
jmtpfs-MtpStorage.$(OBJEXT) jmtpfs-MtpFolder.$(OBJEXT) \
jmtpfs-MtpFile.$(OBJEXT) jmtpfs-TemporaryFile.$(OBJEXT) \
jmtpfs-MtpLocalFileCopy.$(OBJEXT)
jmtpfs-MtpLocalFileCopy.$(OBJEXT) \
jmtpfs-MtpFuseContext.$(OBJEXT)
jmtpfs_OBJECTS = $(am_jmtpfs_OBJECTS)
am__DEPENDENCIES_1 =
jmtpfs_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
@ -183,7 +184,8 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
jmtpfs_SOURCES = jmtpfs.cpp MtpDevice.cpp ConnectedMtpDevices.cpp Mutex.cpp MtpFilesystemPath.cpp \
MtpMetadataCache.cpp MtpNode.cpp MtpRoot.cpp MtpLibLock.cpp MtpStorage.cpp \
MtpFolder.cpp MtpFile.cpp TemporaryFile.cpp MtpLocalFileCopy.cpp
MtpFolder.cpp MtpFile.cpp TemporaryFile.cpp MtpLocalFileCopy.cpp \
MtpFuseContext.cpp
jmtpfs_CPPFLAGS = $(MTP_CFLAGS) $(FUSE_CFLAGS)
jmtpfs_LDADD = $(MTP_LIBS) $(FUSE_LIBS)
@ -273,6 +275,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpFile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpFilesystemPath.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpFolder.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpFuseContext.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpLibLock.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpLocalFileCopy.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jmtpfs-MtpMetadataCache.Po@am__quote@
@ -493,6 +496,20 @@ jmtpfs-MtpLocalFileCopy.obj: MtpLocalFileCopy.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jmtpfs_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o jmtpfs-MtpLocalFileCopy.obj `if test -f 'MtpLocalFileCopy.cpp'; then $(CYGPATH_W) 'MtpLocalFileCopy.cpp'; else $(CYGPATH_W) '$(srcdir)/MtpLocalFileCopy.cpp'; fi`
jmtpfs-MtpFuseContext.o: MtpFuseContext.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jmtpfs_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT jmtpfs-MtpFuseContext.o -MD -MP -MF $(DEPDIR)/jmtpfs-MtpFuseContext.Tpo -c -o jmtpfs-MtpFuseContext.o `test -f 'MtpFuseContext.cpp' || echo '$(srcdir)/'`MtpFuseContext.cpp
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/jmtpfs-MtpFuseContext.Tpo $(DEPDIR)/jmtpfs-MtpFuseContext.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MtpFuseContext.cpp' object='jmtpfs-MtpFuseContext.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jmtpfs_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o jmtpfs-MtpFuseContext.o `test -f 'MtpFuseContext.cpp' || echo '$(srcdir)/'`MtpFuseContext.cpp
jmtpfs-MtpFuseContext.obj: MtpFuseContext.cpp
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jmtpfs_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT jmtpfs-MtpFuseContext.obj -MD -MP -MF $(DEPDIR)/jmtpfs-MtpFuseContext.Tpo -c -o jmtpfs-MtpFuseContext.obj `if test -f 'MtpFuseContext.cpp'; then $(CYGPATH_W) 'MtpFuseContext.cpp'; else $(CYGPATH_W) '$(srcdir)/MtpFuseContext.cpp'; fi`
@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/jmtpfs-MtpFuseContext.Tpo $(DEPDIR)/jmtpfs-MtpFuseContext.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='MtpFuseContext.cpp' object='jmtpfs-MtpFuseContext.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(jmtpfs_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o jmtpfs-MtpFuseContext.obj `if test -f 'MtpFuseContext.cpp'; then $(CYGPATH_W) 'MtpFuseContext.cpp'; else $(CYGPATH_W) '$(srcdir)/MtpFuseContext.cpp'; fi`
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \

View File

@ -60,6 +60,12 @@ public:
MtpDeviceDisconnected(const std::string& message) : MtpError(message, LIBMTP_ERROR_NO_DEVICE_ATTACHED) {}
};
class MtpDeviceNotFound : public MtpError
{
public:
MtpDeviceNotFound(const std::string& message) : MtpError(message, LIBMTP_ERROR_GENERAL) {}
};
class MtpStorageNotFound : public MtpError
{
public:

47
src/MtpFuseContext.cpp Normal file
View File

@ -0,0 +1,47 @@
/*
* MtpFuseContext.cpp
*
* Author: Jason Ferrara
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* This software 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 library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02111-1301, USA.
* licensing@fsf.org
*/
#include "MtpFuseContext.h"
#include "MtpRoot.h"
MtpFuseContext::MtpFuseContext(std::unique_ptr<MtpDevice> device, uid_t uid, gid_t gid) :
m_device(std::move(device)), m_uid(uid), m_gid(gid)
{
}
std::unique_ptr<MtpNode> MtpFuseContext::getNode(const FilesystemPath& path)
{
std::unique_ptr<MtpNode> root(new MtpRoot(*m_device, m_cache));
if (path.Head()=="/")
return root;
else
return root->getNode(path.Body());
}
uid_t MtpFuseContext::uid() const
{
return m_uid;
}
gid_t MtpFuseContext::gid() const
{
return m_gid;
}

49
src/MtpFuseContext.h Normal file
View File

@ -0,0 +1,49 @@
/*
* MtpFuseContext.h
*
* Author: Jason Ferrara
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* This software 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 library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02111-1301, USA.
* licensing@fsf.org
*/
#ifndef MTPFUSECONTEXT_H_
#define MTPFUSECONTEXT_H_
#include "MtpDevice.h"
#include "MtpMetadataCache.h"
#include "MtpNode.h"
#include <memory>
#include <sys/types.h>
class MtpFuseContext
{
public:
MtpFuseContext(std::unique_ptr<MtpDevice> device, uid_t uid, gid_t gid);
std::unique_ptr<MtpNode> getNode(const FilesystemPath& path);
uid_t uid() const;
gid_t gid() const;
protected:
uid_t m_uid;
gid_t m_gid;
std::unique_ptr<MtpDevice> m_device;
MtpMetadataCache m_cache;
};
#endif /* MTPFUSECONTEXT_H_ */

View File

@ -122,3 +122,21 @@ MtpStorageInfo MtpNode::GetStorageInfo()
MtpNodeMetadata md = m_cache.getItem(m_id, *this);
return m_device.GetStorageInfo(md.self.storageId);
}
void MtpNode::statfs(struct statvfs *stat)
{
MtpStorageInfo storageInfo = GetStorageInfo();
stat->f_bsize = 512; // We have to pick some block size, so why not 512?
stat->f_blocks = storageInfo.maxCapacity / stat->f_bsize;
stat->f_bfree = storageInfo.freeSpaceInBytes / stat->f_bsize;
stat->f_bavail = stat->f_bfree;
stat->f_namemax = 233;
}
std::unique_ptr<MtpNode> MtpNode::Clone()
{
throw NotImplemented("Clone");
}

View File

@ -66,6 +66,10 @@ public:
virtual uint32_t FolderId();
virtual uint32_t StorageId();
virtual std::unique_ptr<MtpNode> Clone();
virtual void statfs(struct statvfs *stat);
protected:
uint32_t GetParentNodeId();

View File

@ -94,3 +94,24 @@ MtpStorageInfo MtpRoot::GetStorageInfo()
{
return MtpStorageInfo(0,"",0,0);
}
void MtpRoot::statfs(struct statvfs *stat)
{
size_t totalSize = 0;
size_t totalFree = 0;
std::vector<std::string> storages = readDirectory();
for(std::vector<std::string>::iterator s = storages.begin(); s != storages.end(); s++)
{
MtpStorageInfo info = getNode(FilesystemPath(s->c_str()))->GetStorageInfo();
totalSize += info.maxCapacity;
totalFree += info.freeSpaceInBytes;
}
stat->f_bsize = 512; // We have to pick some block size, so why not 512?
stat->f_blocks = totalSize / stat->f_bsize;
stat->f_bfree = totalFree / stat->f_bsize;
stat->f_bavail = stat->f_bfree;
stat->f_namemax = 233;
}

View File

@ -39,6 +39,8 @@ public:
MtpNodeMetadata getMetadata();
MtpStorageInfo GetStorageInfo();
void statfs(struct statvfs *stat);
};

View File

@ -27,7 +27,10 @@ MtpStorage::MtpStorage(MtpDevice& device, MtpMetadataCache& cache, uint32_t id)
}
std::unique_ptr<MtpNode> MtpStorage::Clone()
{
return std::unique_ptr<MtpNode>(new MtpStorage(m_device, m_cache, m_id));
}

View File

@ -32,6 +32,8 @@ public:
void Remove();
void Rename(MtpNode& newParent, const std::string& newName);
std::unique_ptr<MtpNode> Clone();
};

View File

@ -23,8 +23,9 @@
#include "mtpFilesystemErrors.h"
#include "Mutex.h"
#include "FuseHeader.h"
#include "MtpFuseContext.h"
#include "MtpRoot.h"
#include <MtpRoot.h>
#include <iostream>
#include <cstddef>
#include <errno.h>
@ -47,7 +48,8 @@ RecursiveMutex globalLock;
#define FUSE_ERROR_BLOCK_START \
try \
{ \
LockMutex lock(globalLock);
LockMutex lock(globalLock); \
MtpFuseContext* context((MtpFuseContext*)(fuse_get_context()->private_data)); \
#define FUSE_ERROR_BLOCK_END \
} \
@ -69,28 +71,15 @@ RecursiveMutex globalLock;
}
MtpDevice* currentDevice;
MtpMetadataCache* metadataCache;
std::unique_ptr<MtpNode> getNode(const FilesystemPath& path)
{
if (path.Head() != "/")
throw FileNotFound(path.str());
std::unique_ptr<MtpNode> root(new MtpRoot(*currentDevice, *metadataCache));
FilesystemPath childPath = path.Body();
if (childPath.Empty())
return root;
else
return root->getNode(childPath);
}
extern "C" int jmtpfs_getattr(const char* pathStr, struct stat* info)
{
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->getattr(*info);
context->getNode(path)->getattr(*info);
info->st_uid = context->uid();
info->st_gid = context->gid();
return 0;
FUSE_ERROR_BLOCK_END
@ -103,7 +92,7 @@ extern "C" int jmtpfs_readdir(const char* pathStr, void* buf, fuse_fill_dir_t fi
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
std::unique_ptr<MtpNode> n = getNode(path);
std::unique_ptr<MtpNode> n = context->getNode(path);
std::vector<std::string> contents = n->readdir();
for(std::vector<std::string>::iterator i = contents.begin(); i != contents.end(); i++)
{
@ -121,7 +110,7 @@ extern "C" int jmtpfs_open(const char *pathStr, struct fuse_file_info *)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Open();
context->getNode(path)->Open();
return 0;
FUSE_ERROR_BLOCK_END
@ -132,7 +121,7 @@ extern "C" int jmtpfs_release(const char *pathStr, struct fuse_file_info *)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Close();
context->getNode(path)->Close();
return 0;
FUSE_ERROR_BLOCK_END
@ -143,7 +132,7 @@ extern "C" int jmtpfs_read(const char *pathStr, char *buf, size_t size, off_t o
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
return getNode(path)->Read(buf,size,offset);
return context->getNode(path)->Read(buf,size,offset);
FUSE_ERROR_BLOCK_END
}
@ -153,7 +142,7 @@ extern "C" int jmtpfs_mkdir(const char* pathStr, mode_t mode)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path.AllButTail())->mkdir(path.Tail());
context->getNode(path.AllButTail())->mkdir(path.Tail());
return 0;
FUSE_ERROR_BLOCK_END
@ -164,7 +153,7 @@ extern "C" int jmtpfs_rmdir(const char* pathStr)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Remove();
context->getNode(path)->Remove();
return 0;
FUSE_ERROR_BLOCK_END
@ -176,9 +165,9 @@ extern "C" int jmtpfs_create(const char* pathStr, mode_t mode, struct fuse_file_
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
std::unique_ptr<MtpNode> n = getNode(path.AllButTail());
std::unique_ptr<MtpNode> n = context->getNode(path.AllButTail());
n->CreateFile(path.Tail());
n = getNode(path);
n = context->getNode(path);
n->Open();
return 0;
@ -190,7 +179,7 @@ extern "C" int jmtpfs_write(const char *pathStr, const char *data, size_t size,
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
return getNode(path)->Write(data, size, offset);
return context->getNode(path)->Write(data, size, offset);
FUSE_ERROR_BLOCK_END
}
@ -200,7 +189,7 @@ extern "C" int jmtpfs_truncate(const char *pathStr, off_t length)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Truncate(length);
context->getNode(path)->Truncate(length);
return 0;
FUSE_ERROR_BLOCK_END
@ -211,7 +200,7 @@ extern "C" int jmtpfs_unlink(const char *pathStr)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Remove();
context->getNode(path)->Remove();
return 0;
FUSE_ERROR_BLOCK_END
@ -222,7 +211,7 @@ extern "C" int jmtpfs_flush(const char *pathStr, struct fuse_file_info *)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
getNode(path)->Close();
context->getNode(path)->Close();
return 0;
FUSE_ERROR_BLOCK_END
@ -234,9 +223,9 @@ extern "C" int jmtpfs_rename(const char *pathStr, const char *newPathStr)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
std::unique_ptr<MtpNode> n = getNode(path);
std::unique_ptr<MtpNode> n = context->getNode(path);
FilesystemPath newPath(newPathStr);
std::unique_ptr<MtpNode> newParent = getNode(newPath.AllButTail());
std::unique_ptr<MtpNode> newParent = context->getNode(newPath.AllButTail());
n->Rename(*newParent, newPath.Tail());
return 0;
@ -249,20 +238,8 @@ extern "C" int jmtpfs_statfs(const char *pathStr, struct statvfs *stat)
FUSE_ERROR_BLOCK_START
FilesystemPath path(pathStr);
std::unique_ptr<MtpNode> n = getNode(path);
MtpStorageInfo storageInfo = n->GetStorageInfo();
if (storageInfo.maxCapacity > 0)
{
stat->f_bsize = 512; // We have to pick some block size, so why not 512?
stat->f_blocks = storageInfo.maxCapacity / stat->f_bsize;
stat->f_bfree = storageInfo.freeSpaceInBytes / stat->f_bsize;
stat->f_bavail = stat->f_bfree;
stat->f_namemax = 233;
}
else
stat->f_flag = ST_RDONLY;
std::unique_ptr<MtpNode> n = context->getNode(path);
n->statfs(stat);
return 0;
FUSE_ERROR_BLOCK_END
@ -272,16 +249,20 @@ extern "C" int jmtpfs_statfs(const char *pathStr, struct statvfs *stat)
struct jmtpfs_options
{
jmtpfs_options() : listDevices(0), displayHelp(0),
showVersion(0), device(0) {}
showVersion(0), device(0), listStorage(0) {}
int listDevices;
int displayHelp;
int showVersion;
int listStorage;
char* device;
};
static struct fuse_opt jmtpfs_opts[] = {
{"-l", offsetof(struct jmtpfs_options, listDevices), 1},
{"--listDevices", offsetof(struct jmtpfs_options, listDevices), 1},
// {"-ls", offsetof(struct jmtpfs_options, listStorage), 1},
// {"--listStorage", offsetof(struct jmtpfs_options, listStorage), 1},
{"-h", offsetof(struct jmtpfs_options, displayHelp), 1},
{"-device=%s", offsetof(struct jmtpfs_options, device),0},
{"-V", offsetof(struct jmtpfs_options, showVersion),1},
@ -296,8 +277,7 @@ static struct fuse_operations jmtpfs_oper = {
int main(int argc, char *argv[])
{
std::unique_ptr<MtpDevice> device;
std::unique_ptr<MtpMetadataCache> cache;
LIBMTP_Init();
jmtpfs_oper.getattr = jmtpfs_getattr;
@ -328,6 +308,7 @@ int main(int argc, char *argv[])
{
ConnectedMtpDevices devices;
std::vector<std::string> devListing;
std::vector<std::vector<std::string> > storageDevices;
for(int i=0; i < devices.NumDevices(); i++)
{
ConnectedDeviceInfo devInfo = devices.GetDeviceInfo(i);
@ -337,10 +318,27 @@ int main(int argc, char *argv[])
devText << "0x" << hex << setfill('0') << setw(4)<< devInfo.vendor_id << ", ";
devText << devInfo.product << ", " << devInfo.vendor;
devListing.push_back(devText.str());
if (options.listStorage)
{
std::unique_ptr<MtpDevice> device = devices.GetDevice(i);
std::vector<MtpStorageInfo> storages = device->GetStorageDevices();
std::vector<std::string> storageList;
for(std::vector<MtpStorageInfo>::iterator i = storages.begin(); i != storages.end(); i++)
storageList.push_back(i->description);
storageDevices.push_back(storageList);
}
}
std::cout << "Available devices (busLocation, devNum, productId, vendorId, product, vendor):" << std::endl;
for(std::vector<std::string>::iterator i = devListing.begin(); i != devListing.end(); i++)
std::cout << *i << std::endl;
for(size_t i=0; i<devListing.size(); i++)
{
std::cout << devListing[i] << std::endl;
if (options.listStorage)
{
for(std::vector<std::string>::iterator s = storageDevices[i].begin(); s != storageDevices[i].end(); s++)
std::cout << " " << *s << std::endl;
}
}
return 0;
}
@ -364,6 +362,36 @@ int main(int argc, char *argv[])
}
}
if (options.listStorage)
{
std::unique_ptr<MtpDevice> device;
ConnectedMtpDevices devices;
if (devices.NumDevices()==0)
{
std::cerr << "No mtp devices found." << std::endl;
return -1;
}
try
{
if ((requestedBusLocation!=-1) && (requestedDevnum != -1))
device = devices.GetDevice(0);
else
device = devices.GetDevice(requestedBusLocation, requestedDevnum);
}
catch(MtpDeviceNotFound&)
{
std::cerr << "Requested device not found" << std::endl;
return -1;
}
std::cout << "Storage devices on " << device->Get_Modelname() << ":"<< std::endl;
std::vector<MtpStorageInfo> storages = device->GetStorageDevices();
for(std::vector<MtpStorageInfo>::iterator i = storages.begin(); i != storages.end(); i++)
std::cout << " " << i->description << std::endl;
return 0;
}
std::unique_ptr<MtpFuseContext> context;
if (options.displayHelp)
{
@ -375,32 +403,28 @@ int main(int argc, char *argv[])
}
else
{
currentDevice = 0;
std::unique_ptr<MtpDevice> device;
ConnectedMtpDevices devices;
if (devices.NumDevices()==0)
{
std::cerr << "No mtp devices found." << std::endl;
return -1;
}
for(int i = 0; i<devices.NumDevices(); i++)
try
{
ConnectedDeviceInfo devInfo = devices.GetDeviceInfo(i);
if (((devInfo.bus_location == requestedBusLocation) &&
(devInfo.devnum == requestedDevnum)) ||
(requestedBusLocation == -1) || (requestedDevnum == -1))
{
device = devices.GetDevice(i);
currentDevice = device.get();
break;
}
if ((requestedBusLocation==-1) || (requestedDevnum == -1))
device = devices.GetDevice(0);
else
device = devices.GetDevice(requestedBusLocation, requestedDevnum);
}
if (currentDevice == 0)
catch(MtpDeviceNotFound&)
{
std::cerr << "Requested device not found" << std::endl;
return -1;
}
cache = std::unique_ptr<MtpMetadataCache>(new MtpMetadataCache);
metadataCache = cache.get();
context = std::unique_ptr<MtpFuseContext>(new MtpFuseContext(std::move(device), getuid(), getgid()));
}
if (options.showVersion)
@ -413,12 +437,13 @@ int main(int argc, char *argv[])
std::cout << "Running in the background disabled because of an imcompatiblity between fork and libmtp under Max OS X" << std::endl;
#endif
int result = fuse_main(args.argc, args.argv, &jmtpfs_oper, 0);
int result = fuse_main(args.argc, args.argv, &jmtpfs_oper, context.get());
if (options.displayHelp)
{
std::cout << std::endl << "jmtpfs options:" << std::endl;
std::cout << " -l list available mtp devices and then exit" << std::endl;
std::cout << " -l --listDevices list available mtp devices and then exit" << std::endl;
// std::cout << " -ls --listStorage list the storage areas on the device (or all devices if -l is also specified)" << std::endl;
std::cout << " -device=<busnum>,<devnum> Device to mount. It not specified the first device found is used"<< std::endl;
}