1 ////////////////////////////////////////////////////////////////////////////
3 // Project: SMB kioslave for KDE2
5 // File: kio_smb_file.cpp
7 // Abstract: member function implementations for SMBSlave that deal with
10 // Author(s): Matthew Peterson <mpeterson@caldera.com>
12 //---------------------------------------------------------------------------
14 // Copyright (c) 2000 Caldera Systems, Inc.
16 // This program is free software; you can redistribute it and/or modify it
17 // under the terms of the GNU General Public License as published by the
18 // Free Software Foundation; either version 2.1 of the License, or
19 // (at your option) any later version.
21 // This program is distributed in the hope that it will be useful,
22 // but WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 // GNU Lesser General Public License for more details.
26 // You should have received a copy of the GNU General Public License
27 // along with this program; see the file COPYING. If not, please obtain
28 // a copy from http://www.gnu.org/copyleft/gpl.html
30 /////////////////////////////////////////////////////////////////////////////
34 #include "kio_smb_internal.h"
36 #include <QVarLengthArray>
39 #include <kmimetype.h>
41 //===========================================================================
42 void SMBSlave::get( const KUrl
& kurl
)
44 char buf
[MAX_XFER_BUF_SIZE
];
47 ssize_t bytesread
= 0;
48 // time_t curtime = 0;
51 KIO::filesize_t totalbytesread
= 0;
55 kDebug(KIO_SMB
) << "SMBSlave::get on " << kurl
;
57 // check (correct) URL
58 KUrl kvurl
= checkURL(kurl
);
59 // if URL is not valid we have to redirect to correct URL
66 if(!auth_initialize_smbc())
71 errNum
= cache_stat(url
,&st
);
74 if ( errNum
== EACCES
)
75 error( KIO::ERR_ACCESS_DENIED
, url
.prettyUrl());
77 error( KIO::ERR_DOES_NOT_EXIST
, url
.prettyUrl());
80 if ( S_ISDIR( st
.st_mode
) ) {
81 error( KIO::ERR_IS_DIRECTORY
, url
.prettyUrl());
86 totalSize( st
.st_size
);
88 // Open and read the file
89 filefd
= smbc_open(url
.toSmbcUrl(),O_RDONLY
,0);
92 bool isFirstPacket
= true;
93 lasttime
= starttime
= time(NULL
);
96 bytesread
= smbc_read(filefd
, buf
, MAX_XFER_BUF_SIZE
);
102 else if(bytesread
< 0)
104 error( KIO::ERR_COULD_NOT_READ
, url
.prettyUrl());
108 filedata
= QByteArray::fromRawData(buf
,bytesread
);
111 KMimeType::Ptr p_mimeType
= KMimeType::findByNameAndContent(url
.fileName(), filedata
);
112 mimeType(p_mimeType
->name());
113 isFirstPacket
= false;
118 // increment total bytes read
119 totalbytesread
+= bytesread
;
121 processedSize(totalbytesread
);
125 data( QByteArray() );
126 processedSize(static_cast<KIO::filesize_t
>(st
.st_size
));
131 error( KIO::ERR_CANNOT_OPEN_FOR_READING
, url
.prettyUrl());
139 //===========================================================================
140 void SMBSlave::open( const KUrl
& kurl
, QIODevice::OpenMode mode
)
143 kDebug(KIO_SMB
) << "SMBSlave::open on " << kurl
;
145 // check (correct) URL
146 KUrl kvurl
= checkURL(kurl
);
148 // if URL is not valid we have to redirect to correct URL
155 if(!auth_initialize_smbc()) {
156 error( KIO::ERR_ACCESS_DENIED
, kurl
.prettyUrl());
160 // Save the URL as a private member
161 // FIXME For some reason m_openUrl has be be declared in bottom private
162 // section of the class SMBSlave declaratiom instead of the top section
163 // or else this assignment fails
167 errNum
= cache_stat(m_openUrl
,&st
);
170 if ( errNum
== EACCES
)
171 error( KIO::ERR_ACCESS_DENIED
, m_openUrl
.prettyUrl());
173 error( KIO::ERR_DOES_NOT_EXIST
, m_openUrl
.prettyUrl());
176 if ( S_ISDIR( st
.st_mode
) ) {
177 error( KIO::ERR_IS_DIRECTORY
, m_openUrl
.prettyUrl());
181 // Set the total size
182 totalSize( st
.st_size
);
184 // Convert permissions
186 if (mode
& QIODevice::ReadOnly
) {
187 if (mode
& QIODevice::WriteOnly
) {
188 flags
= O_RDWR
| O_CREAT
;
192 } else if (mode
& QIODevice::WriteOnly
) {
193 flags
= O_WRONLY
| O_CREAT
;
196 if (mode
& QIODevice::Append
) {
198 } else if (mode
& QIODevice::Truncate
) {
203 m_openFd
= smbc_open(m_openUrl
.toSmbcUrl(), flags
, 0);
206 error( KIO::ERR_CANNOT_OPEN_FOR_READING
, m_openUrl
.prettyUrl());
210 // Determine the mimetype of the file to be retrieved, and emit it.
211 // This is mandatory in all slaves (for KRun/BrowserRun to work).
212 // If we're not opening the file ReadOnly or ReadWrite, don't attempt to
213 // read the file and send the mimetype.
214 if (mode
& QIODevice::ReadOnly
){
215 ssize_t bytesRequested
= 1024;
216 ssize_t bytesRead
= 0;
217 QVarLengthArray
<char> buffer(bytesRequested
);
218 bytesRead
= smbc_read(m_openFd
, buffer
.data(), bytesRequested
);
221 error( KIO::ERR_COULD_NOT_READ
, m_openUrl
.prettyUrl());
227 QByteArray fileData
= QByteArray::fromRawData(buffer
.data(),bytesRead
);
228 KMimeType::Ptr p_mimeType
= KMimeType::findByNameAndContent(m_openUrl
.fileName(), fileData
);
229 mimeType(p_mimeType
->name());
231 off_t res
= smbc_lseek(m_openFd
, 0, SEEK_SET
);
232 if (res
== (off_t
)-1) {
233 error(KIO::ERR_COULD_NOT_SEEK
, m_openUrl
.path());
245 void SMBSlave::read( KIO::filesize_t bytesRequested
)
247 Q_ASSERT(m_openFd
!= -1);
249 QVarLengthArray
<char> buffer(bytesRequested
);
250 ssize_t bytesRead
= 0;
252 bytesRead
= smbc_read(m_openFd
, buffer
.data(), bytesRequested
);
253 Q_ASSERT(bytesRead
<= static_cast<ssize_t
>(bytesRequested
));
257 kDebug(KIO_SMB
) << "Could not read " << m_openUrl
;
258 error( KIO::ERR_COULD_NOT_READ
, m_openUrl
.prettyUrl());
263 QByteArray fileData
= QByteArray::fromRawData(buffer
.data(), bytesRead
);
268 void SMBSlave::write(const QByteArray
&fileData
)
270 Q_ASSERT(m_openFd
!= -1);
272 QByteArray
buf(fileData
);
274 ssize_t size
= smbc_write(m_openFd
, buf
.data(), buf
.size());
277 kDebug(KIO_SMB
) << "Could not write to " << m_openUrl
;
278 error( KIO::ERR_COULD_NOT_WRITE
, m_openUrl
.prettyUrl());
286 void SMBSlave::seek(KIO::filesize_t offset
)
288 off_t res
= smbc_lseek(m_openFd
, static_cast<off_t
>(offset
), SEEK_SET
);
289 if (res
== (off_t
)-1) {
290 error(KIO::ERR_COULD_NOT_SEEK
, m_openUrl
.path());
293 kDebug( KIO_SMB
) << "res" << res
;
298 void SMBSlave::close()
300 smbc_close(m_openFd
);
304 //===========================================================================
305 void SMBSlave::put( const KUrl
& kurl
,
307 KIO::JobFlags flags
)
313 m_current_url
= kurl
;
318 off_t retValLSeek
= 0;
322 kDebug(KIO_SMB
) << "SMBSlave::put on " << kurl
;
324 errNum
= cache_stat(m_current_url
, &st
);
325 exists
= (errNum
== 0);
326 if ( exists
&& !(flags
& KIO::Overwrite
) && !(flags
& KIO::Resume
))
328 if (S_ISDIR(st
.st_mode
))
330 kDebug(KIO_SMB
) << "SMBSlave::put on " << kurl
<<" already isdir !!";
331 error( KIO::ERR_DIR_ALREADY_EXIST
, m_current_url
.prettyUrl());
335 kDebug(KIO_SMB
) << "SMBSlave::put on " << kurl
<<" already exist !!";
336 error( KIO::ERR_FILE_ALREADY_EXIST
, m_current_url
.prettyUrl());
341 if (exists
&& !(flags
& KIO::Resume
) && (flags
& KIO::Overwrite
))
343 kDebug(KIO_SMB
) << "SMBSlave::put exists try to remove " << m_current_url
.toSmbcUrl();
344 // remove(m_current_url.url().toLocal8Bit());
348 if (flags
& KIO::Resume
)
350 // append if resuming
351 kDebug(KIO_SMB
) << "SMBSlave::put resume " << m_current_url
.toSmbcUrl();
352 filefd
= smbc_open(m_current_url
.toSmbcUrl(), O_RDWR
, 0 );
359 retValLSeek
= smbc_lseek(filefd
, 0, SEEK_END
);
360 if (retValLSeek
== (off_t
)-1) {
368 if (permissions
!= -1)
370 mode
= permissions
| S_IWUSR
| S_IRUSR
;
377 kDebug(KIO_SMB
) << "SMBSlave::put NO resume " << m_current_url
.toSmbcUrl();
378 filefd
= smbc_open(m_current_url
.toSmbcUrl(), O_CREAT
| O_TRUNC
| O_WRONLY
, mode
);
388 if ( errNum
== EACCES
)
390 kDebug(KIO_SMB
) << "SMBSlave::put error " << kurl
<<" access denied !!";
391 error( KIO::ERR_WRITE_ACCESS_DENIED
, m_current_url
.prettyUrl());
395 kDebug(KIO_SMB
) << "SMBSlave::put error " << kurl
<<" can not open for writing !!";
396 error( KIO::ERR_CANNOT_OPEN_FOR_WRITING
, m_current_url
.prettyUrl());
402 // Loop until we got 0 (end of data)
405 kDebug(KIO_SMB
) << "SMBSlave::put request data ";
406 dataReq(); // Request for data
407 kDebug(KIO_SMB
) << "SMBSlave::put write " << m_current_url
.toSmbcUrl();
409 if (readData(filedata
) <= 0)
411 kDebug(KIO_SMB
) << "readData <= 0";
414 kDebug(KIO_SMB
) << "SMBSlave::put write " << m_current_url
.toSmbcUrl();
415 buf
= filedata
.data();
416 bufsize
= filedata
.size();
417 ssize_t size
= smbc_write(filefd
, buf
, bufsize
);
420 kDebug(KIO_SMB
) << "SMBSlave::put error " << kurl
<<" could not write !!";
421 error( KIO::ERR_COULD_NOT_WRITE
, m_current_url
.prettyUrl());
425 kDebug(KIO_SMB
) << "wrote " << size
;
427 kDebug(KIO_SMB
) << "SMBSlave::put close " << m_current_url
.toSmbcUrl();
429 if(smbc_close(filefd
) < 0)
431 kDebug(KIO_SMB
) << "SMBSlave::put on " << kurl
<<" could not write !!";
432 error( KIO::ERR_COULD_NOT_WRITE
, m_current_url
.prettyUrl());
437 // set final permissions, if the file was just created
438 if ( permissions
!= -1 && !exists
)
440 // TODO: did the smbc_chmod fail?
441 // TODO: put in call to chmod when it is working!
442 // smbc_chmod(url.toSmbcUrl(),permissions);
445 // set modification time
446 const QString mtimeStr
= metaData( "modified" );
447 if ( !mtimeStr
.isEmpty() ) {
448 QDateTime dt
= QDateTime::fromString( mtimeStr
, Qt::ISODate
);
449 if ( dt
.isValid() ) {
450 if (cache_stat( m_current_url
, &st
) == 0) {
451 struct utimbuf utbuf
;
452 utbuf
.actime
= st
.st_atime
; // access time, unchanged
453 utbuf
.modtime
= dt
.toTime_t(); // modification time
454 smbc_utime( m_current_url
.toSmbcUrl(), &utbuf
);
460 // We have done our job => finish