summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/filemanager.cpp308
1 files changed, 98 insertions, 210 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp
index adfe590..47af1c6 100644
--- a/library/filemanager.cpp
+++ b/library/filemanager.cpp
@@ -17,28 +17,18 @@
17** not clear to you. 17** not clear to you.
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/*!
44 \class FileManager 34 \class FileManager
@@ -57,7 +47,6 @@ FileManager::FileManager()
57*/ 47*/
58FileManager::~FileManager() 48FileManager::~FileManager()
59{ 49{
60
61} 50}
62 51
63/*! 52/*!
@@ -67,26 +56,29 @@ FileManager::~FileManager()
67*/ 56*/
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
63 //write data in temporary .new file
64 if ( !file.open( IO_WriteOnly|IO_Raw ) )
65 {
74 qWarning("open failed"); 66 qWarning("open failed");
75 return FALSE; 67 return FALSE;
76 } 68 }
77 int total_written = fl.writeBlock( data ); 69 int total_written = file.writeBlock( data );
78 fl.close(); 70 file.close();
79 if ( total_written != int(data.size()) || !f.writeLink() ) { 71 //check if every was written
80 QFile::remove( fn ); 72 if ( total_written != int(data.size()) || !f.writeLink() )
73 {
74 QFile::remove( fileName );
81 return FALSE; 75 return FALSE;
82 } 76 }
83 qDebug("total written %d out of %d", total_written, data.size()); 77 qDebug("total written %d out of %d", total_written, data.size());
84 // else rename the file... 78
85 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { 79 //rename temporary .new file in original filenam
86 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 80 if ( !renameFile( fileName, f.file() ) )
87 f.file().latin1(), errno ); 81 QFile::remove( fileName);
88 // remove the file...
89 }
90 return TRUE; 82 return TRUE;
91} 83}
92 84
@@ -99,28 +91,30 @@ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
99*/ 91*/
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
98 //write data in temporary .new file
99 if ( !file.open( IO_WriteOnly|IO_Raw ) )
100 {
106 qWarning("open failed"); 101 qWarning("open failed");
107 return FALSE; 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 {
111 QFile::remove( fileName );
116 return FALSE; 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}
126 120
@@ -177,204 +171,94 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
177*/ 171*/
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 187
210 if ( ok ) { 188 if ( ok )
189 {
211 // okay now rename the file... 190 // okay now rename the file...
212 if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) { 191 if ( !renameFile( fileName.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... 192 // remove the tmp file, otherwise, it will just lay around...
216 QFile::remove( fn.latin1() ); 193 QFile::remove( fileName.latin1() );
217 } 194 }
218 } else { 195 else
219 QFile::remove( fn.latin1() ); 196 {
197 QFile::remove( fileName.latin1() );
220 } 198 }
221
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;
229 int write_fd=0;
230 struct stat stat_buf;
231 off_t offset = 0;
232 QFile srcFile(src); 205 QFile srcFile(src);
233 QFile destFile(dest); 206 if( !srcFile.open( IO_ReadOnly|IO_Raw) )
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 { 207 {
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()); 208 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
295 success = false; 209 return 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 }
303
304 return success;
305}
306
307
308bool FileManager::renameFile( const QString & src, const QString & dest ) {
309 if(copyFile( src, dest )) {
310 if(QFile::remove(src) ) {
311 return true;
312 }
313 }
314 return false;
315} 210}
316 211
317/* 212 //open write file
318bool FileManager::copyFile( const QString & src, const QString & dest ) {
319 bool success = true;
320 struct stat status;
321 int read_fd=0;
322 int write_fd=0;
323 struct stat stat_buf;
324 off_t offset = 0;
325 QFile srcFile(src);
326 QFile destFile(dest); 213 QFile destFile(dest);
327
328 if(!srcFile.open( IO_ReadOnly|IO_Raw)) {
329 return success = false;
330 }
331 read_fd = srcFile.handle();
332 if(read_fd != -1) {
333 fstat (read_fd, &stat_buf);
334 if( !destFile.open( IO_WriteOnly|IO_Raw ) ) 214 if( !destFile.open( IO_WriteOnly|IO_Raw ) )
335 return success = false; 215 {
336 write_fd = destFile.handle();
337 if(write_fd != -1) {
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()); 216 qWarning("open write failed %s, %s",src.latin1(), dest.latin1());
352 success = false; 217 srcFile.close();
218 return FALSE;
219 }
220
221 //copy content
222 const int bufsize = 16384;
223 char buffer[bufsize];
224 bool ok = TRUE;
225 int bytesRead = 0;
226 while ( ok && !srcFile.atEnd() )
227 {
228 bytesRead = srcFile.readBlock( buffer, bufsize );
229 if ( bytesRead < 0 )
230 ok = FALSE;
231 while ( ok && bytesRead > 0 )
232 {
233 int bytesWritten = destFile.writeBlock( buffer, bytesRead );
234 if ( bytesWritten < 0 )
235 ok = FALSE;
236 else
237 bytesRead -= bytesWritten;
353 } 238 }
354 } else {
355 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
356 success = false;
357 } 239 }
358 srcFile.close(); 240 srcFile.close();
359 destFile.close(); 241 destFile.close();
360 // Set file permissions 242 // Set file permissions
361 if( stat( (const char *) src, &status ) == 0 ) { 243 struct stat status;
244 if( stat( (const char *) src, &status ) == 0 )
245 {
362 chmod( (const char *) dest, status.st_mode ); 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;
376} 259}
377*/ 260 return true;
261}
378 262
379/*! 263/*!
380 Opens the document specified by \a f as a readable QIODevice. 264 Opens the document specified by \a f as a readable QIODevice.
@@ -386,7 +270,8 @@ QIODevice* FileManager::openFile( const DocLnk& f )
386{ 270{
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 ) )
274 {
390 delete fl; 275 delete fl;
391 fl = 0; 276 fl = 0;
392 } 277 }
@@ -404,9 +289,12 @@ QIODevice* FileManager::saveFile( const DocLnk& f )
404 QString fn = f.file(); 289 QString fn = f.file();
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 ) )
293 {
408 f.writeLink(); 294 f.writeLink();
409 } else { 295 }
296 else
297 {
410 delete fl; 298 delete fl;
411 fl = 0; 299 fl = 0;
412 } 300 }
@@ -422,7 +310,6 @@ bool FileManager::exists( const DocLnk &f )
422 return QFile::exists(f.file()); 310 return QFile::exists(f.file());
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.
428 Returns TRUE if successful. 315 Returns TRUE if successful.
@@ -431,7 +318,8 @@ bool FileManager::ensurePathExists( const QString &fn )
431{ 318{
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() )
322 {
435 if ( system(("mkdir -p "+fi.filePath())) ) 323 if ( system(("mkdir -p "+fi.filePath())) )
436 return FALSE; 324 return FALSE;
437 } 325 }