add more spacing
[personal-kdebase.git] / runtime / kioslave / smb / kio_smb_file.cpp
blob827a519ec0a6e6f0de4d52d923f42c60408243a5
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Project: SMB kioslave for KDE2
4 //
5 // File: kio_smb_file.cpp
6 //
7 // Abstract: member function implementations for SMBSlave that deal with
8 // SMB file access
9 //
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 /////////////////////////////////////////////////////////////////////////////
33 #include "kio_smb.h"
34 #include "kio_smb_internal.h"
36 #include <QVarLengthArray>
37 #include <QDateTime>
39 #include <kmimetype.h>
41 //===========================================================================
42 void SMBSlave::get( const KUrl& kurl )
44 char buf[MAX_XFER_BUF_SIZE];
45 int filefd = 0;
46 int errNum = 0;
47 ssize_t bytesread = 0;
48 // time_t curtime = 0;
49 time_t lasttime = 0;
50 time_t starttime = 0;
51 KIO::filesize_t totalbytesread = 0;
52 QByteArray filedata;
53 SMBUrl url;
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
60 if (kvurl != kurl) {
61 redirection(kvurl);
62 finished();
63 return;
66 if(!auth_initialize_smbc())
67 return;
69 // Stat
70 url = kurl;
71 errNum = cache_stat(url,&st);
72 if( errNum != 0 )
74 if ( errNum == EACCES )
75 error( KIO::ERR_ACCESS_DENIED, url.prettyUrl());
76 else
77 error( KIO::ERR_DOES_NOT_EXIST, url.prettyUrl());
78 return;
80 if ( S_ISDIR( st.st_mode ) ) {
81 error( KIO::ERR_IS_DIRECTORY, url.prettyUrl());
82 return;
85 // Set the total size
86 totalSize( st.st_size );
88 // Open and read the file
89 filefd = smbc_open(url.toSmbcUrl(),O_RDONLY,0);
90 if(filefd >= 0)
92 bool isFirstPacket = true;
93 lasttime = starttime = time(NULL);
94 while(1)
96 bytesread = smbc_read(filefd, buf, MAX_XFER_BUF_SIZE);
97 if(bytesread == 0)
99 // All done reading
100 break;
102 else if(bytesread < 0)
104 error( KIO::ERR_COULD_NOT_READ, url.prettyUrl());
105 return;
108 filedata = QByteArray::fromRawData(buf,bytesread);
109 if (isFirstPacket)
111 KMimeType::Ptr p_mimeType = KMimeType::findByNameAndContent(url.fileName(), filedata);
112 mimeType(p_mimeType->name());
113 isFirstPacket = false;
115 data( filedata );
116 filedata.clear();
118 // increment total bytes read
119 totalbytesread += bytesread;
121 processedSize(totalbytesread);
124 smbc_close(filefd);
125 data( QByteArray() );
126 processedSize(static_cast<KIO::filesize_t>(st.st_size));
129 else
131 error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.prettyUrl());
132 return;
135 finished();
139 //===========================================================================
140 void SMBSlave::open( const KUrl& kurl, QIODevice::OpenMode mode)
142 int errNum = 0;
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
149 if (kvurl != kurl) {
150 redirection(kvurl);
151 finished();
152 return;
155 if(!auth_initialize_smbc()) {
156 error( KIO::ERR_ACCESS_DENIED, kurl.prettyUrl());
157 return;
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
164 m_openUrl = kurl;
166 // Stat
167 errNum = cache_stat(m_openUrl,&st);
168 if( errNum != 0 )
170 if ( errNum == EACCES )
171 error( KIO::ERR_ACCESS_DENIED, m_openUrl.prettyUrl());
172 else
173 error( KIO::ERR_DOES_NOT_EXIST, m_openUrl.prettyUrl());
174 return;
176 if ( S_ISDIR( st.st_mode ) ) {
177 error( KIO::ERR_IS_DIRECTORY, m_openUrl.prettyUrl());
178 return;
181 // Set the total size
182 totalSize( st.st_size );
184 // Convert permissions
185 int flags = 0;
186 if (mode & QIODevice::ReadOnly) {
187 if (mode & QIODevice::WriteOnly) {
188 flags = O_RDWR | O_CREAT;
189 } else {
190 flags = O_RDONLY;
192 } else if (mode & QIODevice::WriteOnly) {
193 flags = O_WRONLY | O_CREAT;
196 if (mode & QIODevice::Append) {
197 flags |= O_APPEND;
198 } else if (mode & QIODevice::Truncate) {
199 flags |= O_TRUNC;
202 // Open the file
203 m_openFd = smbc_open(m_openUrl.toSmbcUrl(), flags, 0);
204 if(m_openFd < 0)
206 error( KIO::ERR_CANNOT_OPEN_FOR_READING, m_openUrl.prettyUrl());
207 return;
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);
219 if(bytesRead < 0)
221 error( KIO::ERR_COULD_NOT_READ, m_openUrl.prettyUrl());
222 close();
223 return;
225 else
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());
234 close();
235 return;
240 position( 0 );
241 emit opened();
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));
255 if(bytesRead < 0)
257 kDebug(KIO_SMB) << "Could not read " << m_openUrl;
258 error( KIO::ERR_COULD_NOT_READ, m_openUrl.prettyUrl());
259 close();
260 return;
263 QByteArray fileData = QByteArray::fromRawData(buffer.data(), bytesRead);
264 data( fileData );
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());
275 if (size < 0)
277 kDebug(KIO_SMB) << "Could not write to " << m_openUrl;
278 error( KIO::ERR_COULD_NOT_WRITE, m_openUrl.prettyUrl());
279 close();
280 return;
283 written(size);
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());
291 close();
292 } else {
293 kDebug( KIO_SMB ) << "res" << res;
294 position( res );
298 void SMBSlave::close()
300 smbc_close(m_openFd);
301 finished();
304 //===========================================================================
305 void SMBSlave::put( const KUrl& kurl,
306 int permissions,
307 KIO::JobFlags flags )
310 void *buf;
311 size_t bufsize;
313 m_current_url = kurl;
315 int filefd;
316 bool exists;
317 int errNum = 0;
318 off_t retValLSeek = 0;
319 mode_t mode;
320 QByteArray filedata;
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());
333 else
335 kDebug(KIO_SMB) << "SMBSlave::put on " << kurl <<" already exist !!";
336 error( KIO::ERR_FILE_ALREADY_EXIST, m_current_url.prettyUrl());
338 return;
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 );
353 if (filefd < 0) {
354 errNum = errno;
355 } else {
356 errNum = 0;
359 retValLSeek = smbc_lseek(filefd, 0, SEEK_END);
360 if (retValLSeek == (off_t)-1) {
361 errNum = errno;
362 } else {
363 errNum = 0;
366 else
368 if (permissions != -1)
370 mode = permissions | S_IWUSR | S_IRUSR;
372 else
374 mode = 600;//0666;
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);
379 if (filefd < 0) {
380 errNum = errno;
381 } else {
382 errNum = 0;
386 if ( filefd < 0 )
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());
393 else
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());
398 finished();
399 return;
402 // Loop until we got 0 (end of data)
403 while(1)
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";
412 break;
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);
418 if ( size < 0)
420 kDebug(KIO_SMB) << "SMBSlave::put error " << kurl <<" could not write !!";
421 error( KIO::ERR_COULD_NOT_WRITE, m_current_url.prettyUrl());
422 finished();
423 return;
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());
433 finished();
434 return;
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);
444 #ifdef HAVE_UTIME_H
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 );
458 #endif
460 // We have done our job => finish
461 finished();