1 /****************************************************************************************
2  * Copyright (c) 2006-2007 Maximilian Kossick <maximilian.kossick@googlemail.com>       *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16 
17 #define DEBUG_PREFIX "MassStorageDeviceHandler"
18 
19 #include "MassStorageDeviceHandler.h"
20 
21 #include "core/support/Debug.h"
22 #include <core/storage/SqlStorage.h>
23 
24 #include <QUrl>
25 #include <QDir>
26 #include <Solid/Device>
27 #include <Solid/StorageAccess>
28 #include <Solid/StorageVolume>
29 
MassStorageDeviceHandler()30 MassStorageDeviceHandler::MassStorageDeviceHandler(): DeviceHandler()
31 {
32 }
33 
MassStorageDeviceHandler(int deviceId,const QString & mountPoint,const QString & udi)34 MassStorageDeviceHandler::MassStorageDeviceHandler( int deviceId, const QString &mountPoint, const QString &udi )
35     : DeviceHandler()
36     , m_deviceID( deviceId )
37     , m_mountPoint( mountPoint )
38     , m_udi( udi )
39 {
40     DEBUG_BLOCK
41 }
42 
~MassStorageDeviceHandler()43 MassStorageDeviceHandler::~MassStorageDeviceHandler()
44 {
45 }
46 
isAvailable() const47 bool MassStorageDeviceHandler::isAvailable() const
48 {
49     return true;
50 }
51 
52 
type() const53 QString MassStorageDeviceHandler::type() const
54 {
55     return "uuid";
56 }
57 
getDeviceID()58 int MassStorageDeviceHandler::getDeviceID()
59 {
60     return m_deviceID;
61 }
62 
getDevicePath() const63 const QString &MassStorageDeviceHandler::getDevicePath() const
64 {
65     return m_mountPoint;
66 }
67 
getURL(QUrl & absolutePath,const QUrl & relativePath)68 void MassStorageDeviceHandler::getURL( QUrl &absolutePath, const QUrl &relativePath )
69 {
70     absolutePath.setPath( m_mountPoint );
71     absolutePath = absolutePath.adjusted(QUrl::StripTrailingSlash);
72     absolutePath.setPath(absolutePath.path() + QLatin1Char('/') + ( relativePath.path() ));
73     absolutePath.setPath( QDir::cleanPath(absolutePath.path()) );
74 }
75 
getPlayableURL(QUrl & absolutePath,const QUrl & relativePath)76 void MassStorageDeviceHandler::getPlayableURL( QUrl &absolutePath, const QUrl &relativePath )
77 {
78     getURL( absolutePath, relativePath );
79 }
80 
deviceMatchesUdi(const QString & udi) const81 bool MassStorageDeviceHandler::deviceMatchesUdi( const QString &udi ) const
82 {
83     return m_udi == udi;
84 }
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 // class MassStorageDeviceHandlerFactory
88 ///////////////////////////////////////////////////////////////////////////////
89 
type() const90 QString MassStorageDeviceHandlerFactory::type( ) const
91 {
92     return "uuid";
93 }
94 
canCreateFromMedium() const95 bool MassStorageDeviceHandlerFactory::canCreateFromMedium( ) const
96 {
97     return true;
98 }
99 
canCreateFromConfig() const100 bool MassStorageDeviceHandlerFactory::canCreateFromConfig( ) const
101 {
102     return false;
103 }
104 
canHandle(const Solid::Device & device) const105 bool MassStorageDeviceHandlerFactory::canHandle( const Solid::Device &device ) const
106 {
107     DEBUG_BLOCK
108     const Solid::StorageVolume *volume = device.as<Solid::StorageVolume>();
109     if( !volume )
110     {
111         debug() << "found no volume";
112         return false;
113     }
114     if( volume->uuid().isEmpty() )
115         debug() << "has empty uuid";
116     if( volume->isIgnored() )
117         debug() << "volume is ignored";
118     if( excludedFilesystem( volume->fsType() ) )
119         debug() << "excluded filesystem of type " << volume->fsType();
120     return volume && !volume->uuid().isEmpty()
121            && !volume->isIgnored() && !excludedFilesystem( volume->fsType() );
122 }
123 
~MassStorageDeviceHandlerFactory()124 MassStorageDeviceHandlerFactory::~MassStorageDeviceHandlerFactory( )
125 {
126 }
127 
createHandler(const KSharedConfigPtr &,QSharedPointer<SqlStorage>) const128 DeviceHandler * MassStorageDeviceHandlerFactory::createHandler( const KSharedConfigPtr&, QSharedPointer<SqlStorage> ) const
129 {
130     return 0;
131 }
132 
createHandler(const Solid::Device & device,const QString & udi,QSharedPointer<SqlStorage> s) const133 DeviceHandler * MassStorageDeviceHandlerFactory::createHandler( const Solid::Device &device, const QString &udi, QSharedPointer<SqlStorage> s ) const
134 {
135     DEBUG_BLOCK
136     if( !s )
137     {
138         debug() << "!s, returning 0";
139         return 0;
140     }
141     const Solid::StorageVolume *volume = device.as<Solid::StorageVolume>();
142     const Solid::StorageAccess *volumeAccess = device.as<Solid::StorageAccess>();
143     if( !volume || !volumeAccess )
144     {
145         debug() << "Volume isn't valid, can't create a handler";
146         return 0;
147     }
148     if( volumeAccess->filePath().isEmpty() )
149     {
150         debug() << "not mounted, can't do anything";
151         return 0; // It's not mounted, we can't do anything.
152     }
153     QStringList ids = s->query( QString( "SELECT id, label, lastmountpoint "
154                                          "FROM devices WHERE type = 'uuid' "
155                                          "AND uuid = '%1';" ).arg( volume->uuid() ) );
156     if ( ids.size() == 3 )
157     {
158         debug() << "Found existing UUID config for ID " << ids[0] << " , uuid " << volume->uuid();
159         s->query( QString( "UPDATE devices SET lastmountpoint = '%2' WHERE "
160                            "id = %1;" )
161                            .arg( ids[0],
162                                  s->escape( volumeAccess->filePath() ) ) );
163         return new MassStorageDeviceHandler( ids[0].toInt(), volumeAccess->filePath(), udi );
164     }
165     else
166     {
167         const int id = s->insert( QString( "INSERT INTO devices( type, uuid, lastmountpoint ) "
168                                            "VALUES ( 'uuid', '%1', '%2' );" )
169                                            .arg( volume->uuid(),
170                                                  s->escape( volumeAccess->filePath() ) ),
171                                            "devices" );
172         if ( id == 0 )
173         {
174             warning() << "Inserting into devices failed for type=uuid, uuid=" << volume->uuid();
175             return 0;
176         }
177         debug() << "Created new UUID device with ID " << id << " , uuid " << volume->uuid();
178         return new MassStorageDeviceHandler( id, volumeAccess->filePath(), udi );
179     }
180 }
181 
182 bool
excludedFilesystem(const QString & fstype) const183 MassStorageDeviceHandlerFactory::excludedFilesystem( const QString &fstype ) const
184 {
185     return fstype.isEmpty() ||
186            fstype.indexOf( "smb" ) != -1 ||
187            fstype.indexOf( "cifs" ) != -1 ||
188            fstype.indexOf( "nfs" ) != -1 ||
189            fstype == "udf"  ||
190            fstype == "iso9660" ;
191 }
192