1 /****************************************************************************************
2  * Copyright (c) 2006-2007 Maximilian Kossick <maximilian.kossick@googlemail.com>       *
3  * Copyright (c) 2011 Peter C. Ndikuwera <pndiku@gmail.com>                             *
4  *                                                                                      *
5  * This program is free software; you can redistribute it and/or modify it under        *
6  * the terms of the GNU General Public License as published by the Free Software        *
7  * Foundation; either version 2 of the License, or (at your option) any later           *
8  * version.                                                                             *
9  *                                                                                      *
10  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
12  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
13  *                                                                                      *
14  * You should have received a copy of the GNU General Public License along with         *
15  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
16  ****************************************************************************************/
17 
18 #define DEBUG_PREFIX "NfsDeviceHandler"
19 
20 #include "NfsDeviceHandler.h"
21 
22 #include "core/support/Debug.h"
23 #include <core/storage/SqlStorage.h>
24 
25 #include <QUrl>
26 #include <QDir>
27 #include <Solid/Device>
28 #include <Solid/StorageAccess>
29 #include <Solid/NetworkShare>
30 
NfsDeviceHandler(int deviceId,const QString & server,const QString & share,const QString & mountPoint,const QString & udi)31 NfsDeviceHandler::NfsDeviceHandler( int deviceId, const QString &server, const QString &share, const QString &mountPoint, const QString &udi )
32     : DeviceHandler()
33     , m_deviceID( deviceId )
34     , m_server( server )
35     , m_share( share )
36     , m_mountPoint( mountPoint )
37     , m_udi( udi )
38 {
39   DEBUG_BLOCK
40 }
41 
NfsDeviceHandler(int deviceId,const QString & mountPoint,const QString & udi)42 NfsDeviceHandler::NfsDeviceHandler( int deviceId, const QString &mountPoint, const QString &udi )
43     : DeviceHandler()
44     , m_deviceID( deviceId )
45     , m_mountPoint( mountPoint )
46     , m_udi( udi )
47 {
48   DEBUG_BLOCK
49 }
50 
~NfsDeviceHandler()51 NfsDeviceHandler::~NfsDeviceHandler()
52 {
53 }
54 
55 bool
isAvailable() const56 NfsDeviceHandler::isAvailable() const
57 {
58     return true;
59 }
60 
61 
62 QString
type() const63 NfsDeviceHandler::type() const
64 {
65     return "nfs";
66 }
67 
68 int
getDeviceID()69 NfsDeviceHandler::getDeviceID()
70 {
71     return m_deviceID;
72 }
73 
getDevicePath() const74 const QString &NfsDeviceHandler::getDevicePath() const
75 {
76     return m_mountPoint;
77 }
78 
getURL(QUrl & absolutePath,const QUrl & relativePath)79 void NfsDeviceHandler::getURL( QUrl &absolutePath, const QUrl &relativePath )
80 {
81     absolutePath.setPath( m_mountPoint );
82     absolutePath = absolutePath.adjusted(QUrl::StripTrailingSlash);
83     absolutePath.setPath(absolutePath.path() + QLatin1Char('/') + ( relativePath.path() ));
84     absolutePath.setPath( QDir::cleanPath(absolutePath.path()) );
85 }
86 
getPlayableURL(QUrl & absolutePath,const QUrl & relativePath)87 void NfsDeviceHandler::getPlayableURL( QUrl &absolutePath, const QUrl &relativePath )
88 {
89     getURL( absolutePath, relativePath );
90 }
91 
deviceMatchesUdi(const QString & udi) const92 bool NfsDeviceHandler::deviceMatchesUdi( const QString &udi ) const
93 {
94   return m_udi == udi;
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 // class NfsDeviceHandlerFactory
99 ///////////////////////////////////////////////////////////////////////////////
100 
type() const101 QString NfsDeviceHandlerFactory::type( ) const
102 {
103     return "nfs";
104 }
105 
canCreateFromMedium() const106 bool NfsDeviceHandlerFactory::canCreateFromMedium( ) const
107 {
108     return true;
109 }
110 
canCreateFromConfig() const111 bool NfsDeviceHandlerFactory::canCreateFromConfig( ) const
112 {
113     return false;
114 }
115 
canHandle(const Solid::Device & device) const116 bool NfsDeviceHandlerFactory::canHandle( const Solid::Device &device ) const
117 {
118     const Solid::NetworkShare *share = device.as<Solid::NetworkShare>();
119     if( !share )
120     {
121         debug() << __PRETTY_FUNCTION__ << device.udi() << "has no NetworkShare interface";
122         return false;
123     }
124     if( share->type() != Solid::NetworkShare::Nfs )
125     {
126         debug() << __PRETTY_FUNCTION__ << device.udi() << "has type" << share->type()
127                 << "but nfs type is" << Solid::NetworkShare::Nfs;
128         return false;
129     }
130     const Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
131     if( !access )
132     {
133         debug() << __PRETTY_FUNCTION__ << device.udi() << "has no StorageAccess interface";
134         return false;
135     }
136     if( !access->isAccessible() || access->filePath().isEmpty() )
137     {
138         debug() << __PRETTY_FUNCTION__ << device.udi() << "is not accessible"
139                 << "or has empty mount-point";
140         return false;
141     }
142     return true;
143 }
144 
~NfsDeviceHandlerFactory()145 NfsDeviceHandlerFactory::~NfsDeviceHandlerFactory( )
146 {
147 }
148 
149 DeviceHandler *
createHandler(const KSharedConfigPtr &,QSharedPointer<SqlStorage>) const150 NfsDeviceHandlerFactory::createHandler( const KSharedConfigPtr&, QSharedPointer<SqlStorage> ) const
151 {
152     return nullptr;
153 }
154 
155 DeviceHandler *
createHandler(const Solid::Device & device,const QString & udi,QSharedPointer<SqlStorage> s) const156 NfsDeviceHandlerFactory::createHandler( const Solid::Device &device, const QString &udi, QSharedPointer<SqlStorage> s ) const
157 {
158     DEBUG_BLOCK
159     if( !s )
160     {
161         debug() << "!s, returning 0";
162         return nullptr;
163     }
164     if( !canHandle( device ) )
165         return nullptr;
166 
167     const Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
168     Q_ASSERT( access );  // canHandle() checks it
169     QString mountPoint = access->filePath();
170 
171     const Solid::NetworkShare *netShare = device.as<Solid::NetworkShare>();
172     Q_ASSERT( netShare );  // canHandle() checks it
173     QUrl url = netShare->url(); // nfs://thinkpad/test or nfs://thinkpad/
174     QString server = url.host();
175     QString share = url.path(); // leading slash is preserved for nfs shares
176 
177     QStringList ids = s->query( QString( "SELECT id, label, lastmountpoint "
178                                          "FROM devices WHERE type = 'nfs' "
179                                          "AND servername = '%1' AND sharename = '%2';" )
180                                          .arg( s->escape( server ),
181                                                s->escape( share ) ) );
182     if ( ids.size() == 3 )
183     {
184         debug() << "Found existing NFS config for ID " << ids[0] << " , server " << server << " ,share " << share;
185         s->query( QString( "UPDATE devices SET lastmountpoint = '%2' WHERE "
186                            "id = %1;" )
187                            .arg( ids[0],
188                                  s->escape( mountPoint ) ) );
189         return new NfsDeviceHandler( ids[0].toInt(), server, share, mountPoint, udi );
190     }
191     else
192     {
193         int id = s->insert( QString( "INSERT INTO devices"
194                                      "( type, servername, sharename, lastmountpoint ) "
195                                      "VALUES ( 'nfs', '%1', '%2', '%3' );" )
196                                      .arg( s->escape( server ),
197                                            s->escape( share ),
198                                            s->escape( mountPoint ) ),
199                                      "devices" );
200         if ( id == 0 )
201         {
202             warning() << "Inserting into devices failed for type=nfs, server=" << server << ", share=" << share;
203             return nullptr;
204         }
205         debug() << "Created new NFS device with ID " << id << " , server " << server << " ,share " << share;
206         return new NfsDeviceHandler( id, server, share, mountPoint, udi );
207     }
208 }
209