1
/**************************************************************************
3
* Copyright 2015 Canonical Ltd.
4
* Copyright 2015 Carlos J Mazieri <carlos.mazieri@gmail.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation; version 3.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
* File: smblocationitemfile.cpp
22
#include "smblocationitemfile.h"
23
#include "smbiteminfo.h"
26
#include <sys/statfs.h>
32
SmbLocationItemFile::SmbLocationItemFile(QObject *parent, Const_SmbUtil_Ptr smb)
33
: LocationItemFile(parent)
34
, SmbObject(QLatin1String(0), smb)
37
, m_curReadPosition(0)
43
SmbLocationItemFile::SmbLocationItemFile(const QString &name, QObject *parent, Const_SmbUtil_Ptr smb)
44
: LocationItemFile(parent)
45
, SmbObject(name, smb)
48
, m_curReadPosition(0)
55
SmbLocationItemFile::~SmbLocationItemFile()
60
SmbObject::smbObj()->deleteContext(m_context);
66
QString SmbLocationItemFile::fileName() const
72
bool SmbLocationItemFile::rename(const QString& newName)
75
if (!cleanUrl().isEmpty())
78
ret = rename(cleanUrl(), newName);
84
bool SmbLocationItemFile::rename(const QString& oldname, const QString& newName)
87
Smb::Context nContext = SmbObject::smbObj()->createContext();
88
int ret = smbc_getFunctionRename(m_context)
90
oldname.toLocal8Bit().constData(),
92
newName.toLocal8Bit().constData()
94
SmbObject::smbObj()->deleteContext(nContext);
99
bool SmbLocationItemFile::remove()
101
return private_remove(cleanUrl());
105
bool SmbLocationItemFile::remove(const QString& name)
107
CleanUrl otherUrl(name);
108
if (otherUrl.hasAuthenticationData())
110
qWarning() << Q_FUNC_INFO
111
<< "Authentication in the form smb://user:password@pathname is not supported" ;
113
return private_remove(name) ;
117
bool SmbLocationItemFile::link(const QString& linkName)
120
qWarning() << Q_FUNC_INFO << "Smbclient does not provide link() function";
125
bool SmbLocationItemFile::open(QIODevice::OpenMode mode)
128
QString smb_path = cleanUrl();
129
if (!smb_path.isEmpty() && !isOpen())
134
if (mode & QFile::ReadOnly)
136
openFlags = mode & QFile::WriteOnly ? O_RDWR : O_RDONLY;
140
if (mode & QFile::WriteOnly)
142
openFlags = O_CREAT | O_WRONLY;
144
if (mode & QFile::Append)
146
openFlags = O_APPEND | O_CREAT | O_WRONLY;
148
if ((mode & QFile::Truncate) || !(mode & QFile::Append))
150
openFlags |= O_TRUNC;
153
int creationMode = LocationItemFile::getUmaskFilesCreation();
155
* it looks like SMB open() does set the permission properly
156
* does not matter what value "creationMode" has, libsmbclient always creates files with the following permission:
157
* -rwxr--r-- 1 nobody nogroup 0 Mai 30 14:04 second_item.txt
158
* SMB chmod() does not work either
160
* It depends on Samba configuration: force user; force group; force create mode; force directory mode
162
m_fd = SmbObject::smbObj()->openFile(m_context, smb_path, openFlags, creationMode);
163
ret = m_fd ? true : false;
169
qint64 SmbLocationItemFile::read(char * buffer, qint64 bytes)
174
size_t to_write = static_cast<size_t> (bytes);
175
void *buf = static_cast<void*> (buffer);
176
ssize_t wr = smbc_getFunctionRead(m_context)(m_context, m_fd, buf, to_write);
177
ret = static_cast<qint64> (wr);
181
m_curReadPosition += ret;
187
qint64 SmbLocationItemFile::write(const char * buffer, qint64 bytes)
192
size_t to_read = static_cast<size_t> (bytes);
193
const void * const_buf = static_cast<const void*> (buffer);
194
void *buf = const_cast<void*> (const_buf);
195
ssize_t rd = smbc_getFunctionWrite(m_context)(m_context, m_fd, buf, to_read);
196
ret = static_cast<qint64> (rd);
202
void SmbLocationItemFile::close()
206
SmbObject::smbObj()->closeHandle(m_context, m_fd);
209
m_curReadPosition = 0;
213
bool SmbLocationItemFile::atEnd() const
215
bool ret = true; //closed files are at end, aren't they?
219
if (smbObj()->getFstat(m_context,m_fd, &st) == SmbUtil::StatDone)
221
ret = m_curReadPosition >= st.st_size;
228
qint64 SmbLocationItemFile::size() const
232
bool ok = isOpen() ? smbObj()->getFstat(m_context,m_fd,&st) == 0 : false;
235
ok = m_context != 0 ? smbObj()->getStat(m_context,cleanUrl(),&st) == 0 :
236
smbObj()->getStatInfo(cleanUrl(),&st) == SmbUtil::StatDone;
240
size = static_cast<qint64> (st.st_size);
246
bool SmbLocationItemFile::isOpen() const
248
return m_fd != 0 && m_context != 0 ? true : false;
252
bool SmbLocationItemFile::setPermissions(QFileDevice::Permissions perm)
254
return setPermissions(cleanUrl(), perm);
258
bool SmbLocationItemFile::setPermissions(const QString &filename, QFileDevice::Permissions perm)
261
if (!filename.isEmpty())
263
createContextIfNotExists();
264
ret = smbObj()->changePermissions(m_context, filename, LocationItemFile::unixPermissions(perm));
266
* fake the return in case the file exists becase chmod() on libsmbclient does not work,
267
* the same comment is present in the \ref open()
272
ret = smbObj()->getStat(m_context,filename, &st) == SmbUtil::StatDone;
279
QFile::Permissions SmbLocationItemFile::permissions() const
281
SmbItemInfo info(cleanUrl(), m_smb);
282
return info.permissions();
286
bool SmbLocationItemFile::private_remove(const QString& smb_path)
289
if (!smb_path.isEmpty())
292
createContextIfNotExists();
293
if (smbc_getFunctionUnlink(m_context)(m_context, smb_path.toLocal8Bit().constData()) == 0)
303
* \brief SmbLocationItemFile::createContext() Always creates a new context, if a context already exists it is deleted.
305
void SmbLocationItemFile::createContext()
309
SmbObject::smbObj()->deleteContext(m_context);
311
m_context = SmbObject::smbObj()->createContext();
317
* \brief SmbLocationItemFile::createContextIfNotExists() Creates a new context when the current context is null
319
* It tries to reuse an existent context
321
void SmbLocationItemFile::createContextIfNotExists()
325
m_context = SmbObject::smbObj()->createContext();