summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/filemanager.cpp372
1 files changed, 130 insertions, 242 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp
index adfe590..47af1c6 100644
--- a/library/filemanager.cpp
+++ b/library/filemanager.cpp
@@ -18,26 +18,16 @@
18** 18**
19**********************************************************************/ 19**********************************************************************/
20
20#include "filemanager.h" 21#include "filemanager.h"
21#include "applnk.h" 22#include "applnk.h"
22 23
24/* QT */
25#include <qdir.h>
23#include <qfileinfo.h> 26#include <qfileinfo.h>
24#include <qtextstream.h> 27#include <qtextstream.h>
25 28
26#include <errno.h> 29/* STD */
27#include <stdlib.h> 30#include <stdlib.h>
28#include <unistd.h>
29#include <sys/stat.h> 31#include <sys/stat.h>
30#include <dirent.h>
31#ifdef Q_OS_MACX
32// MacOS X does not have sendfile.. :(
33// But maybe in the future.. !?
34# ifdef SENDFILE
35# include <sys/types.h>
36# include <sys/socket.h>
37# endif
38#else
39# include <sys/sendfile.h>
40#endif /* Q_OS_MACX */
41#include <fcntl.h>
42 32
43/*! 33/*!
@@ -58,5 +48,4 @@ FileManager::FileManager()
58FileManager::~FileManager() 48FileManager::~FileManager()
59{ 49{
60
61} 50}
62 51
@@ -68,24 +57,27 @@ FileManager::~FileManager()
68bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) 57bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
69{ 58{
70 QString fn = f.file() + ".new"; 59 QString fileName = f.file() + ".new";
71 ensurePathExists( fn ); 60 ensurePathExists( fileName );
72 QFile fl( fn ); 61 QFile file( fileName );
73 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { 62
74 qWarning("open failed"); 63 //write data in temporary .new file
75 return FALSE; 64 if ( !file.open( IO_WriteOnly|IO_Raw ) )
76 } 65 {
77 int total_written = fl.writeBlock( data ); 66 qWarning("open failed");
78 fl.close(); 67 return FALSE;
79 if ( total_written != int(data.size()) || !f.writeLink() ) {
80 QFile::remove( fn );
81 return FALSE;
82 } 68 }
83 qDebug("total written %d out of %d", total_written, data.size()); 69 int total_written = file.writeBlock( data );
84 // else rename the file... 70 file.close();
85 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { 71 //check if every was written
86 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 72 if ( total_written != int(data.size()) || !f.writeLink() )
87 f.file().latin1(), errno ); 73 {
88 // remove the file... 74 QFile::remove( fileName );
75 return FALSE;
89 } 76 }
77 qDebug("total written %d out of %d", total_written, data.size());
78
79 //rename temporary .new file in original filenam
80 if ( !renameFile( fileName, f.file() ) )
81 QFile::remove( fileName);
90 return TRUE; 82 return TRUE;
91} 83}
@@ -100,26 +92,28 @@ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
100bool FileManager::saveFile( const DocLnk &f, const QString &text ) 92bool FileManager::saveFile( const DocLnk &f, const QString &text )
101{ 93{
102 QString fn = f.file() + ".new"; 94 QString fileName = f.file() + ".new";
103 ensurePathExists( fn ); 95 ensurePathExists( fileName );
104 QFile fl( fn ); 96 QFile file( fileName );
105 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { 97
106 qWarning("open failed"); 98 //write data in temporary .new file
107 return FALSE; 99 if ( !file.open( IO_WriteOnly|IO_Raw ) )
100 {
101 qWarning("open failed");
102 return FALSE;
108 } 103 }
109 104
110 QCString cstr = text.utf8(); 105 QCString cstr = text.utf8();
111 int total_written; 106 int total_written;
112 total_written = fl.writeBlock( cstr.data(), cstr.length() ); 107 total_written = file.writeBlock( cstr.data(), cstr.length() );
113 fl.close(); 108 file.close();
114 if ( total_written != int(cstr.length()) || !f.writeLink() ) { 109 if ( total_written != int(cstr.length()) || !f.writeLink() )
115 QFile::remove( fn ); 110 {
116 return FALSE; 111 QFile::remove( fileName );
112 return FALSE;
117 } 113 }
118 // okay now rename the file..
119 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) {
120 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
121 f.file().latin1(), errno );
122 114
123 } 115 // okay now rename the file..
116 if ( !renameFile( fileName, f.file() ) )
117 QFile::remove( fileName);
124 return TRUE; 118 return TRUE;
125} 119}
@@ -138,5 +132,5 @@ bool FileManager::loadFile( const DocLnk &f, QString &text )
138 QFile fl( fn ); 132 QFile fl( fn );
139 if ( !fl.open( IO_ReadOnly ) ) 133 if ( !fl.open( IO_ReadOnly ) )
140 return FALSE; 134 return FALSE;
141 QTextStream ts( &fl ); 135 QTextStream ts( &fl );
142#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 136#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
@@ -162,8 +156,8 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
162 QFile fl( fn ); 156 QFile fl( fn );
163 if ( !fl.open( IO_ReadOnly ) ) 157 if ( !fl.open( IO_ReadOnly ) )
164 return FALSE; 158 return FALSE;
165 ba.resize( fl.size() ); 159 ba.resize( fl.size() );
166 if ( fl.size() > 0 ) 160 if ( fl.size() > 0 )
167 fl.readBlock( ba.data(), fl.size() ); 161 fl.readBlock( ba.data(), fl.size() );
168 fl.close(); 162 fl.close();
169 return TRUE; 163 return TRUE;
@@ -178,202 +172,92 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
178bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) 172bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest )
179{ 173{
180 QFile sf( src.file() ); 174 QFile srcFile( src.file() );
181 if ( !sf.open( IO_ReadOnly ) ) 175 if ( !srcFile.open( IO_ReadOnly ) )
182 return FALSE; 176 return FALSE;
183 177
184 QString fn = dest.file() + ".new"; 178 QString fileName = dest.file() + ".new";
185 ensurePathExists( fn ); 179
186 QFile df( fn ); 180 ensurePathExists( fileName );
187 if ( !df.open( IO_WriteOnly|IO_Raw ) )
188 return FALSE;
189 181
190 const int bufsize = 16384;
191 char buffer[bufsize];
192 bool ok = TRUE; 182 bool ok = TRUE;
193 int bytesRead = 0; 183 ok = copyFile( src.file(), fileName );
194 while ( ok && !sf.atEnd() ) {
195 bytesRead = sf.readBlock( buffer, bufsize );
196 if ( bytesRead < 0 )
197 ok = FALSE;
198 while ( ok && bytesRead > 0 ) {
199 int bytesWritten = df.writeBlock( buffer, bytesRead );
200 if ( bytesWritten < 0 )
201 ok = FALSE;
202 else
203 bytesRead -= bytesWritten;
204 }
205 }
206 184
207 if ( ok ) 185 if ( ok )
208 ok = dest.writeLink(); 186 ok = dest.writeLink();
209
210 if ( ok ) {
211 // okay now rename the file...
212 if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) {
213 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
214 dest.file().latin1(), errno );
215 // remove the tmp file, otherwise, it will just lay around...
216 QFile::remove( fn.latin1() );
217 }
218 } else {
219 QFile::remove( fn.latin1() );
220 }
221 187
188 if ( ok )
189 {
190 // okay now rename the file...
191 if ( !renameFile( fileName.latin1(), dest.file().latin1() ) )
192 // remove the tmp file, otherwise, it will just lay around...
193 QFile::remove( fileName.latin1() );
194 }
195 else
196 {
197 QFile::remove( fileName.latin1() );
198 }
222 return ok; 199 return ok;
223} 200}
224 201
225bool FileManager::copyFile( const QString & src, const QString & dest ) { 202bool FileManager::copyFile( const QString & src, const QString & dest )
226 bool success = true; 203{
227 struct stat status; 204 //open read file
228 int read_fd=0; 205 QFile srcFile( src );
229 int write_fd=0; 206 if( !srcFile.open( IO_ReadOnly|IO_Raw) )
230 struct stat stat_buf; 207 {
231 off_t offset = 0; 208 qWarning( "open read failed %s, %s", src.latin1(), dest.latin1() );
232 QFile srcFile(src); 209 return FALSE;
233 QFile destFile(dest);
234
235 if(!srcFile.open( IO_ReadOnly|IO_Raw)) {
236 return success = false;
237 }
238 read_fd = srcFile.handle();
239 if(read_fd != -1) {
240 fstat (read_fd, &stat_buf);
241 if( !destFile.open( IO_WriteOnly|IO_Raw ) )
242 return success = false;
243 write_fd = destFile.handle();
244 if(write_fd != -1) {
245 int err=0;
246 QString msg;
247#ifdef Q_OS_MACX
248#ifdef SENDFILE
249 /* FreeBSD does support a different kind of
250 * sendfile. (eilers)
251 * I took this from Very Secure FTPd
252 * Licence: GPL
253 * Author: Chris Evans
254 * sysdeputil.c
255 */
256 /* XXX - start_pos will truncate on 32-bit machines - can we
257 * say "start from current pos"?
258 */
259 off_t written = 0;
260 int retval = 0;
261 retval = sendfile(read_fd, write_fd, offset, stat_buf.st_size, NULL,
262 &written, 0);
263 /* Translate to Linux-like retval */
264 if (written > 0)
265 {
266 err = (int) written;
267 }
268#else /* SENDFILE */
269 err == -1;
270 msg = "FAILURE: Using unsupported function \"sendfile()\" Need Workaround !!";
271 success = false;
272# warning "Need workaround for sendfile!!(eilers)"
273#endif /* SENDFILE */
274
275#else
276 err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size);
277 if( err == -1) {
278 switch(errno) {
279 case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. ";
280 case EINVAL: msg = "Descriptor is not valid or locked. ";
281 case ENOMEM: msg = "Insufficient memory to read from in_fd.";
282 case EIO: msg = "Unspecified error while reading from in_fd.";
283 };
284 success = false;
285 }
286#endif /* Q_OS_MACX */
287 if( !success )
288 qWarning( msg );
289 } else {
290 qWarning("open write failed %s, %s",src.latin1(), dest.latin1());
291 success = false;
292 }
293 } else {
294 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
295 success = false;
296 }
297 srcFile.close();
298 destFile.close();
299 // Set file permissions
300 if( stat( (const char *) src, &status ) == 0 ) {
301 chmod( (const char *) dest, status.st_mode );
302 } 210 }
303 211
304 return success; 212 //open write file
305} 213 QFile destFile( dest );
306 214 if( !destFile.open( IO_WriteOnly|IO_Raw ) )
307 215 {
308bool FileManager::renameFile( const QString & src, const QString & dest ) { 216 qWarning( "open write failed %s, %s", src.latin1(), dest.latin1() );
309 if(copyFile( src, dest )) { 217 srcFile.close();
310 if(QFile::remove(src) ) { 218 return FALSE;
311 return true; 219 }
312 }
313 }
314 return false;
315}
316 220
317/* 221 //copy content
318bool FileManager::copyFile( const QString & src, const QString & dest ) { 222 const int bufsize = 16384;
319 bool success = true; 223 char buffer[bufsize];
320 struct stat status; 224 bool ok = TRUE;
321 int read_fd=0; 225 int bytesRead = 0;
322 int write_fd=0; 226 while ( ok && !srcFile.atEnd() )
323 struct stat stat_buf; 227 {
324 off_t offset = 0; 228 bytesRead = srcFile.readBlock( buffer, bufsize );
325 QFile srcFile(src); 229 if ( bytesRead < 0 )
326 QFile destFile(dest); 230 ok = FALSE;
327 231 while ( ok && bytesRead > 0 )
328 if(!srcFile.open( IO_ReadOnly|IO_Raw)) { 232 {
329 return success = false; 233 int bytesWritten = destFile.writeBlock( buffer, bytesRead );
330 } 234 if ( bytesWritten < 0 )
331 read_fd = srcFile.handle(); 235 ok = FALSE;
332 if(read_fd != -1) { 236 else
333 fstat (read_fd, &stat_buf); 237 bytesRead -= bytesWritten;
334 if( !destFile.open( IO_WriteOnly|IO_Raw ) ) 238 }
335 return success = false; 239 }
336 write_fd = destFile.handle(); 240 srcFile.close();
337 if(write_fd != -1) { 241 destFile.close();
338 int err=0;
339 QString msg;
340 err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size);
341 if( err == -1) {
342 switch(err) {
343 case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. ";
344 case EINVAL: msg = "Descriptor is not valid or locked. ";
345 case ENOMEM: msg = "Insufficient memory to read from in_fd.";
346 case EIO: msg = "Unspecified error while reading from in_fd.";
347 };
348 success = false;
349 }
350 } else {
351 qWarning("open write failed %s, %s",src.latin1(), dest.latin1());
352 success = false;
353 }
354 } else {
355 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
356 success = false;
357 }
358 srcFile.close();
359 destFile.close();
360 // Set file permissions 242 // Set file permissions
361 if( stat( (const char *) src, &status ) == 0 ) { 243 struct stat status;
362 chmod( (const char *) dest, status.st_mode ); 244 if( stat( (const char *) src, &status ) == 0 )
245 {
246 chmod( (const char *) dest, status.st_mode );
363 } 247 }
364 248 return ok;
365 return success;
366} 249}
367 250
368 251
369bool FileManager::renameFile( const QString & src, const QString & dest ) { 252bool FileManager::renameFile( const QString & src, const QString & dest )
370 if(copyFile( src, dest )) { 253{
371 if(QFile::remove(src) ) { 254 QDir dir( QFileInfo( src ).absFilePath() );
372 return true; 255 if ( !dir.rename( src, dest ) )
373 } 256 {
374 } 257 qWarning( "problem renaming file %s to %s", src, dest );
375 return false; 258 return false;
259 }
260 return true;
376} 261}
377*/
378 262
379/*! 263/*!
@@ -387,6 +271,7 @@ QIODevice* FileManager::openFile( const DocLnk& f )
387 QString fn = f.file(); 271 QString fn = f.file();
388 QFile* fl = new QFile( fn ); 272 QFile* fl = new QFile( fn );
389 if ( !fl->open( IO_ReadOnly ) ) { 273 if ( !fl->open( IO_ReadOnly ) )
390 delete fl; 274 {
275 delete fl;
391 fl = 0; 276 fl = 0;
392 } 277 }
@@ -405,8 +290,11 @@ QIODevice* FileManager::saveFile( const DocLnk& f )
405 ensurePathExists( fn ); 290 ensurePathExists( fn );
406 QFile* fl = new QFile( fn ); 291 QFile* fl = new QFile( fn );
407 if ( fl->open( IO_WriteOnly ) ) { 292 if ( fl->open( IO_WriteOnly ) )
408 f.writeLink(); 293 {
409 } else { 294 f.writeLink();
410 delete fl; 295 }
296 else
297 {
298 delete fl;
411 fl = 0; 299 fl = 0;
412 } 300 }
@@ -423,5 +311,4 @@ bool FileManager::exists( const DocLnk &f )
423} 311}
424 312
425
426/*! 313/*!
427 Ensures that the path \a fn exists, by creating required directories. 314 Ensures that the path \a fn exists, by creating required directories.
@@ -432,7 +319,8 @@ bool FileManager::ensurePathExists( const QString &fn )
432 QFileInfo fi(fn); 319 QFileInfo fi(fn);
433 fi.setFile( fi.dirPath(TRUE) ); 320 fi.setFile( fi.dirPath(TRUE) );
434 if ( !fi.exists() ) { 321 if ( !fi.exists() )
435 if ( system(("mkdir -p "+fi.filePath())) ) 322 {
436 return FALSE; 323 if ( system(("mkdir -p "+fi.filePath())) )
324 return FALSE;
437 } 325 }
438 326