mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 02:42:50 +00:00
463 lines
13 KiB
C++
463 lines
13 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Project: SMB kioslave for KDE2
|
|
//
|
|
// File: kio_smb_file.cpp
|
|
//
|
|
// Abstract: member function implementations for SMBSlave that deal with
|
|
// SMB file access
|
|
//
|
|
// Author(s): Matthew Peterson <mpeterson@caldera.com>
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 2000 Caldera Systems, Inc.
|
|
//
|
|
// 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.1 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 Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; see the file COPYING. If not, please obtain
|
|
// a copy from http://www.gnu.org/copyleft/gpl.html
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "kio_smb.h"
|
|
#include "kio_smb_internal.h"
|
|
|
|
#include <QVarLengthArray>
|
|
#include <QDateTime>
|
|
|
|
#include <kmimetype.h>
|
|
|
|
//===========================================================================
|
|
void SMBSlave::get( const KUrl& kurl )
|
|
{
|
|
char buf[MAX_XFER_BUF_SIZE];
|
|
int filefd = 0;
|
|
int errNum = 0;
|
|
ssize_t bytesread = 0;
|
|
// time_t curtime = 0;
|
|
time_t lasttime = 0;
|
|
time_t starttime = 0;
|
|
KIO::filesize_t totalbytesread = 0;
|
|
QByteArray filedata;
|
|
SMBUrl url;
|
|
|
|
kDebug(KIO_SMB) << kurl;
|
|
|
|
// check (correct) URL
|
|
KUrl kvurl = checkURL(kurl);
|
|
// if URL is not valid we have to redirect to correct URL
|
|
if (kvurl != kurl) {
|
|
redirection(kvurl);
|
|
finished();
|
|
return;
|
|
}
|
|
|
|
if(!auth_initialize_smbc())
|
|
return;
|
|
|
|
// Stat
|
|
url = kurl;
|
|
errNum = cache_stat(url,&st);
|
|
if( errNum != 0 )
|
|
{
|
|
if ( errNum == EACCES )
|
|
error( KIO::ERR_ACCESS_DENIED, url.prettyUrl());
|
|
else
|
|
error( KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
|
|
return;
|
|
}
|
|
if ( S_ISDIR( st.st_mode ) ) {
|
|
error( KIO::ERR_IS_DIRECTORY, url.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
// Set the total size
|
|
totalSize( st.st_size );
|
|
|
|
// Open and read the file
|
|
filefd = smbc_open(url.toSmbcUrl(),O_RDONLY,0);
|
|
if(filefd >= 0)
|
|
{
|
|
bool isFirstPacket = true;
|
|
lasttime = starttime = time(NULL);
|
|
while(1)
|
|
{
|
|
bytesread = smbc_read(filefd, buf, MAX_XFER_BUF_SIZE);
|
|
if(bytesread == 0)
|
|
{
|
|
// All done reading
|
|
break;
|
|
}
|
|
else if(bytesread < 0)
|
|
{
|
|
error( KIO::ERR_COULD_NOT_READ, url.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
filedata = QByteArray::fromRawData(buf,bytesread);
|
|
if (isFirstPacket)
|
|
{
|
|
KMimeType::Ptr p_mimeType = KMimeType::findByNameAndContent(url.fileName(), filedata);
|
|
mimeType(p_mimeType->name());
|
|
isFirstPacket = false;
|
|
}
|
|
data( filedata );
|
|
filedata.clear();
|
|
|
|
// increment total bytes read
|
|
totalbytesread += bytesread;
|
|
|
|
processedSize(totalbytesread);
|
|
}
|
|
|
|
smbc_close(filefd);
|
|
data( QByteArray() );
|
|
processedSize(static_cast<KIO::filesize_t>(st.st_size));
|
|
|
|
}
|
|
else
|
|
{
|
|
error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
finished();
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
void SMBSlave::open( const KUrl& kurl, QIODevice::OpenMode mode)
|
|
{
|
|
int errNum = 0;
|
|
kDebug(KIO_SMB) << kurl;
|
|
|
|
// check (correct) URL
|
|
KUrl kvurl = checkURL(kurl);
|
|
|
|
// if URL is not valid we have to redirect to correct URL
|
|
if (kvurl != kurl) {
|
|
redirection(kvurl);
|
|
finished();
|
|
return;
|
|
}
|
|
|
|
if(!auth_initialize_smbc()) {
|
|
error( KIO::ERR_ACCESS_DENIED, kurl.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
// Save the URL as a private member
|
|
// FIXME For some reason m_openUrl has be be declared in bottom private
|
|
// section of the class SMBSlave declaratiom instead of the top section
|
|
// or else this assignment fails
|
|
m_openUrl = kurl;
|
|
|
|
// Stat
|
|
errNum = cache_stat(m_openUrl,&st);
|
|
if( errNum != 0 )
|
|
{
|
|
if ( errNum == EACCES )
|
|
error( KIO::ERR_ACCESS_DENIED, m_openUrl.prettyUrl());
|
|
else
|
|
error( KIO::ERR_DOES_NOT_EXIST, m_openUrl.prettyUrl());
|
|
return;
|
|
}
|
|
if ( S_ISDIR( st.st_mode ) ) {
|
|
error( KIO::ERR_IS_DIRECTORY, m_openUrl.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
// Set the total size
|
|
totalSize( st.st_size );
|
|
|
|
// Convert permissions
|
|
int flags = 0;
|
|
if (mode & QIODevice::ReadOnly) {
|
|
if (mode & QIODevice::WriteOnly) {
|
|
flags = O_RDWR | O_CREAT;
|
|
} else {
|
|
flags = O_RDONLY;
|
|
}
|
|
} else if (mode & QIODevice::WriteOnly) {
|
|
flags = O_WRONLY | O_CREAT;
|
|
}
|
|
|
|
if (mode & QIODevice::Append) {
|
|
flags |= O_APPEND;
|
|
} else if (mode & QIODevice::Truncate) {
|
|
flags |= O_TRUNC;
|
|
}
|
|
|
|
// Open the file
|
|
m_openFd = smbc_open(m_openUrl.toSmbcUrl(), flags, 0);
|
|
if(m_openFd < 0)
|
|
{
|
|
error( KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
// Determine the mimetype of the file to be retrieved, and emit it.
|
|
// This is mandatory in all slaves (for KRun/BrowserRun to work).
|
|
// If we're not opening the file ReadOnly or ReadWrite, don't attempt to
|
|
// read the file and send the mimetype.
|
|
if (mode & QIODevice::ReadOnly){
|
|
ssize_t bytesRequested = 1024;
|
|
ssize_t bytesRead = 0;
|
|
QVarLengthArray<char> buffer(bytesRequested);
|
|
bytesRead = smbc_read(m_openFd, buffer.data(), bytesRequested);
|
|
if(bytesRead < 0)
|
|
{
|
|
error( KIO::ERR_COULD_NOT_READ, m_openUrl.prettyUrl());
|
|
close();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
QByteArray fileData = QByteArray::fromRawData(buffer.data(),bytesRead);
|
|
KMimeType::Ptr p_mimeType = KMimeType::findByNameAndContent(m_openUrl.fileName(), fileData);
|
|
mimeType(p_mimeType->name());
|
|
|
|
off_t res = smbc_lseek(m_openFd, 0, SEEK_SET);
|
|
if (res == (off_t)-1) {
|
|
error(KIO::ERR_COULD_NOT_SEEK, m_openUrl.path());
|
|
close();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
position( 0 );
|
|
emit opened();
|
|
}
|
|
|
|
|
|
void SMBSlave::read( KIO::filesize_t bytesRequested )
|
|
{
|
|
Q_ASSERT(m_openFd != -1);
|
|
|
|
QVarLengthArray<char> buffer(bytesRequested);
|
|
ssize_t bytesRead = 0;
|
|
|
|
bytesRead = smbc_read(m_openFd, buffer.data(), bytesRequested);
|
|
Q_ASSERT(bytesRead <= static_cast<ssize_t>(bytesRequested));
|
|
|
|
if(bytesRead < 0)
|
|
{
|
|
kDebug(KIO_SMB) << "Could not read " << m_openUrl;
|
|
error( KIO::ERR_COULD_NOT_READ, m_openUrl.prettyUrl());
|
|
close();
|
|
return;
|
|
}
|
|
|
|
QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead);
|
|
data( fileData );
|
|
}
|
|
|
|
|
|
void SMBSlave::write(const QByteArray &fileData)
|
|
{
|
|
Q_ASSERT(m_openFd != -1);
|
|
|
|
QByteArray buf(fileData);
|
|
|
|
ssize_t size = smbc_write(m_openFd, buf.data(), buf.size());
|
|
if (size < 0)
|
|
{
|
|
kDebug(KIO_SMB) << "Could not write to " << m_openUrl;
|
|
error( KIO::ERR_COULD_NOT_WRITE, m_openUrl.prettyUrl());
|
|
close();
|
|
return;
|
|
}
|
|
|
|
written(size);
|
|
}
|
|
|
|
void SMBSlave::seek(KIO::filesize_t offset)
|
|
{
|
|
off_t res = smbc_lseek(m_openFd, static_cast<off_t>(offset), SEEK_SET);
|
|
if (res == (off_t)-1) {
|
|
error(KIO::ERR_COULD_NOT_SEEK, m_openUrl.path());
|
|
close();
|
|
} else {
|
|
kDebug( KIO_SMB ) << "res" << res;
|
|
position( res );
|
|
}
|
|
}
|
|
|
|
void SMBSlave::close()
|
|
{
|
|
smbc_close(m_openFd);
|
|
finished();
|
|
}
|
|
|
|
//===========================================================================
|
|
void SMBSlave::put( const KUrl& kurl,
|
|
int permissions,
|
|
KIO::JobFlags flags )
|
|
{
|
|
|
|
void *buf;
|
|
size_t bufsize;
|
|
|
|
m_current_url = kurl;
|
|
|
|
int filefd;
|
|
bool exists;
|
|
int errNum = 0;
|
|
off_t retValLSeek = 0;
|
|
mode_t mode;
|
|
QByteArray filedata;
|
|
|
|
kDebug(KIO_SMB) << kurl;
|
|
|
|
errNum = cache_stat(m_current_url, &st);
|
|
exists = (errNum == 0);
|
|
if ( exists && !(flags & KIO::Overwrite) && !(flags & KIO::Resume))
|
|
{
|
|
if (S_ISDIR(st.st_mode))
|
|
{
|
|
kDebug(KIO_SMB) << kurl <<" already isdir !!";
|
|
error( KIO::ERR_DIR_ALREADY_EXIST, m_current_url.prettyUrl());
|
|
}
|
|
else
|
|
{
|
|
kDebug(KIO_SMB) << kurl <<" already exist !!";
|
|
error( KIO::ERR_FILE_ALREADY_EXIST, m_current_url.prettyUrl());
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (exists && !(flags & KIO::Resume) && (flags & KIO::Overwrite))
|
|
{
|
|
kDebug(KIO_SMB) << "exists try to remove " << m_current_url.toSmbcUrl();
|
|
// remove(m_current_url.url().toLocal8Bit());
|
|
}
|
|
|
|
|
|
if (flags & KIO::Resume)
|
|
{
|
|
// append if resuming
|
|
kDebug(KIO_SMB) << "resume " << m_current_url.toSmbcUrl();
|
|
filefd = smbc_open(m_current_url.toSmbcUrl(), O_RDWR, 0 );
|
|
if (filefd < 0) {
|
|
errNum = errno;
|
|
} else {
|
|
errNum = 0;
|
|
}
|
|
|
|
retValLSeek = smbc_lseek(filefd, 0, SEEK_END);
|
|
if (retValLSeek == (off_t)-1) {
|
|
errNum = errno;
|
|
} else {
|
|
errNum = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (permissions != -1)
|
|
{
|
|
mode = permissions | S_IWUSR | S_IRUSR;
|
|
}
|
|
else
|
|
{
|
|
mode = 600;//0666;
|
|
}
|
|
|
|
kDebug(KIO_SMB) << "NO resume " << m_current_url.toSmbcUrl();
|
|
filefd = smbc_open(m_current_url.toSmbcUrl(), O_CREAT | O_TRUNC | O_WRONLY, mode);
|
|
if (filefd < 0) {
|
|
errNum = errno;
|
|
} else {
|
|
errNum = 0;
|
|
}
|
|
}
|
|
|
|
if ( filefd < 0 )
|
|
{
|
|
if ( errNum == EACCES )
|
|
{
|
|
kDebug(KIO_SMB) << "error " << kurl <<" access denied !!";
|
|
error( KIO::ERR_WRITE_ACCESS_DENIED, m_current_url.prettyUrl());
|
|
}
|
|
else
|
|
{
|
|
kDebug(KIO_SMB) << "error " << kurl <<" can not open for writing !!";
|
|
error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, m_current_url.prettyUrl());
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Loop until we got 0 (end of data)
|
|
while(1)
|
|
{
|
|
kDebug(KIO_SMB) << "request data ";
|
|
dataReq(); // Request for data
|
|
kDebug(KIO_SMB) << "write " << m_current_url.toSmbcUrl();
|
|
|
|
if (readData(filedata) <= 0)
|
|
{
|
|
kDebug(KIO_SMB) << "readData <= 0";
|
|
break;
|
|
}
|
|
kDebug(KIO_SMB) << "write " << m_current_url.toSmbcUrl();
|
|
buf = filedata.data();
|
|
bufsize = filedata.size();
|
|
ssize_t size = smbc_write(filefd, buf, bufsize);
|
|
if ( size < 0)
|
|
{
|
|
kDebug(KIO_SMB) << "error " << kurl << "could not write !!";
|
|
error( KIO::ERR_COULD_NOT_WRITE, m_current_url.prettyUrl());
|
|
return;
|
|
}
|
|
kDebug(KIO_SMB ) << "wrote " << size;
|
|
}
|
|
kDebug(KIO_SMB) << "close " << m_current_url.toSmbcUrl();
|
|
|
|
if(smbc_close(filefd) < 0)
|
|
{
|
|
kDebug(KIO_SMB) << kurl << "could not write !!";
|
|
error( KIO::ERR_COULD_NOT_WRITE, m_current_url.prettyUrl());
|
|
return;
|
|
}
|
|
|
|
// set final permissions, if the file was just created
|
|
if ( permissions != -1 && !exists )
|
|
{
|
|
// TODO: did the smbc_chmod fail?
|
|
// TODO: put in call to chmod when it is working!
|
|
// smbc_chmod(url.toSmbcUrl(),permissions);
|
|
}
|
|
#ifdef HAVE_UTIME_H
|
|
// set modification time
|
|
const QString mtimeStr = metaData( "modified" );
|
|
if ( !mtimeStr.isEmpty() ) {
|
|
QDateTime dt = QDateTime::fromString( mtimeStr, Qt::ISODate );
|
|
if ( dt.isValid() ) {
|
|
if (cache_stat( m_current_url, &st ) == 0) {
|
|
struct utimbuf utbuf;
|
|
utbuf.actime = st.st_atime; // access time, unchanged
|
|
utbuf.modtime = dt.toTime_t(); // modification time
|
|
smbc_utime( m_current_url.toSmbcUrl(), &utbuf );
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// We have done our job => finish
|
|
finished();
|
|
}
|
|
|
|
|
|
|
|
|