summaryrefslogtreecommitdiff
path: root/library/filemanager.cpp
Unidiff
Diffstat (limited to 'library/filemanager.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/filemanager.cpp67
1 files changed, 55 insertions, 12 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp
index cc657fa..91986a0 100644
--- a/library/filemanager.cpp
+++ b/library/filemanager.cpp
@@ -1,341 +1,384 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20#include "filemanager.h" 20#include "filemanager.h"
21#include "applnk.h" 21#include "applnk.h"
22 22
23#include <qdir.h> 23#include <qdir.h>
24#include <qfile.h> 24#include <qfile.h>
25#include <qfileinfo.h> 25#include <qfileinfo.h>
26#include <qtextstream.h> 26#include <qtextstream.h>
27#include <qtextcodec.h> 27#include <qtextcodec.h>
28 28
29#include <errno.h> 29#include <errno.h>
30#include <stdlib.h> 30#include <stdlib.h>
31#include <unistd.h> 31#include <unistd.h>
32#include <sys/stat.h> 32#include <sys/stat.h>
33#include <dirent.h> 33#include <dirent.h>
34#include <sys/sendfile.h> 34#ifdef Q_OS_MACX
35// MacOS X does not have sendfile.. :(
36// But maybe in the future.. !?
37# ifdef SENDFILE
38# include <sys/types.h>
39# include <sys/socket.h>
40# endif
41#else
42# include <sys/sendfile.h>
43#endif /* Q_OS_MACX */
35#include <fcntl.h> 44#include <fcntl.h>
36 45
37/*! 46/*!
38 \class FileManager 47 \class FileManager
39 \brief The FileManager class assists with AppLnk input/output. 48 \brief The FileManager class assists with AppLnk input/output.
40*/ 49*/
41 50
42/*! 51/*!
43 Constructs a FileManager. 52 Constructs a FileManager.
44*/ 53*/
45FileManager::FileManager() 54FileManager::FileManager()
46{ 55{
47} 56}
48 57
49/*! 58/*!
50 Destroys a FileManager. 59 Destroys a FileManager.
51*/ 60*/
52FileManager::~FileManager() 61FileManager::~FileManager()
53{ 62{
54 63
55} 64}
56 65
57/*! 66/*!
58 Saves \a data as the document specified by \a f. 67 Saves \a data as the document specified by \a f.
59 68
60 Returns whether the operation succeeded. 69 Returns whether the operation succeeded.
61*/ 70*/
62bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) 71bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
63{ 72{
64 QString fn = f.file() + ".new"; 73 QString fn = f.file() + ".new";
65 ensurePathExists( fn ); 74 ensurePathExists( fn );
66 QFile fl( fn ); 75 QFile fl( fn );
67 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { 76 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) {
68 qWarning("open failed"); 77 qWarning("open failed");
69 return FALSE; 78 return FALSE;
70 } 79 }
71 int total_written = fl.writeBlock( data ); 80 int total_written = fl.writeBlock( data );
72 fl.close(); 81 fl.close();
73 if ( total_written != int(data.size()) || !f.writeLink() ) { 82 if ( total_written != int(data.size()) || !f.writeLink() ) {
74 QFile::remove( fn ); 83 QFile::remove( fn );
75 return FALSE; 84 return FALSE;
76 } 85 }
77 qDebug("total written %d out of %d", total_written, data.size()); 86 qDebug("total written %d out of %d", total_written, data.size());
78 // else rename the file... 87 // else rename the file...
79 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { 88 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) {
80 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 89 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
81 f.file().latin1(), errno ); 90 f.file().latin1(), errno );
82 // remove the file... 91 // remove the file...
83 } 92 }
84 return TRUE; 93 return TRUE;
85} 94}
86 95
87/*! 96/*!
88 Saves \a text as the document specified by \a f. 97 Saves \a text as the document specified by \a f.
89 98
90 The text is saved in UTF8 format. 99 The text is saved in UTF8 format.
91 100
92 Returns whether the operation succeeded. 101 Returns whether the operation succeeded.
93*/ 102*/
94bool FileManager::saveFile( const DocLnk &f, const QString &text ) 103bool FileManager::saveFile( const DocLnk &f, const QString &text )
95{ 104{
96 QString fn = f.file() + ".new"; 105 QString fn = f.file() + ".new";
97 ensurePathExists( fn ); 106 ensurePathExists( fn );
98 QFile fl( fn ); 107 QFile fl( fn );
99 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { 108 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) {
100 qWarning("open failed"); 109 qWarning("open failed");
101 return FALSE; 110 return FALSE;
102 } 111 }
103 112
104 QCString cstr = text.utf8(); 113 QCString cstr = text.utf8();
105 int total_written; 114 int total_written;
106 total_written = fl.writeBlock( cstr.data(), cstr.length() ); 115 total_written = fl.writeBlock( cstr.data(), cstr.length() );
107 fl.close(); 116 fl.close();
108 if ( total_written != int(cstr.length()) || !f.writeLink() ) { 117 if ( total_written != int(cstr.length()) || !f.writeLink() ) {
109 QFile::remove( fn ); 118 QFile::remove( fn );
110 return FALSE; 119 return FALSE;
111 } 120 }
112 // okay now rename the file.. 121 // okay now rename the file..
113 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) { 122 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) {
114 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 123 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
115 f.file().latin1(), errno ); 124 f.file().latin1(), errno );
116 125
117 } 126 }
118 return TRUE; 127 return TRUE;
119} 128}
120 129
121 130
122/*! 131/*!
123 Loads \a text from the document specified by \a f. 132 Loads \a text from the document specified by \a f.
124 133
125 The text is required to be in UTF8 format. 134 The text is required to be in UTF8 format.
126 135
127 Returns whether the operation succeeded. 136 Returns whether the operation succeeded.
128*/ 137*/
129bool FileManager::loadFile( const DocLnk &f, QString &text ) 138bool FileManager::loadFile( const DocLnk &f, QString &text )
130{ 139{
131 QString fn = f.file(); 140 QString fn = f.file();
132 QFile fl( fn ); 141 QFile fl( fn );
133 if ( !fl.open( IO_ReadOnly ) ) 142 if ( !fl.open( IO_ReadOnly ) )
134 return FALSE; 143 return FALSE;
135 QTextStream ts( &fl ); 144 QTextStream ts( &fl );
136#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 145#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
137 // The below should work, but doesn't in Qt 2.3.0 146 // The below should work, but doesn't in Qt 2.3.0
138 ts.setCodec( QTextCodec::codecForMib( 106 ) ); 147 ts.setCodec( QTextCodec::codecForMib( 106 ) );
139#else 148#else
140 ts.setEncoding( QTextStream::UnicodeUTF8 ); 149 ts.setEncoding( QTextStream::UnicodeUTF8 );
141#endif 150#endif
142 text = ts.read(); 151 text = ts.read();
143 fl.close(); 152 fl.close();
144 return TRUE; 153 return TRUE;
145} 154}
146 155
147 156
148/*! 157/*!
149 Loads \a ba from the document specified by \a f. 158 Loads \a ba from the document specified by \a f.
150 159
151 Returns whether the operation succeeded. 160 Returns whether the operation succeeded.
152*/ 161*/
153bool FileManager::loadFile( const DocLnk &f, QByteArray &ba ) 162bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
154{ 163{
155 QString fn = f.file(); 164 QString fn = f.file();
156 QFile fl( fn ); 165 QFile fl( fn );
157 if ( !fl.open( IO_ReadOnly ) ) 166 if ( !fl.open( IO_ReadOnly ) )
158 return FALSE; 167 return FALSE;
159 ba.resize( fl.size() ); 168 ba.resize( fl.size() );
160 if ( fl.size() > 0 ) 169 if ( fl.size() > 0 )
161 fl.readBlock( ba.data(), fl.size() ); 170 fl.readBlock( ba.data(), fl.size() );
162 fl.close(); 171 fl.close();
163 return TRUE; 172 return TRUE;
164} 173}
165 174
166/*! 175/*!
167 Copies the document specified by \a src to the document specified 176 Copies the document specified by \a src to the document specified
168 by \a dest. 177 by \a dest.
169 178
170 Returns whether the operation succeeded. 179 Returns whether the operation succeeded.
171*/ 180*/
172bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) 181bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest )
173{ 182{
174 QFile sf( src.file() ); 183 QFile sf( src.file() );
175 if ( !sf.open( IO_ReadOnly ) ) 184 if ( !sf.open( IO_ReadOnly ) )
176 return FALSE; 185 return FALSE;
177 186
178 QString fn = dest.file() + ".new"; 187 QString fn = dest.file() + ".new";
179 ensurePathExists( fn ); 188 ensurePathExists( fn );
180 QFile df( fn ); 189 QFile df( fn );
181 if ( !df.open( IO_WriteOnly|IO_Raw ) ) 190 if ( !df.open( IO_WriteOnly|IO_Raw ) )
182 return FALSE; 191 return FALSE;
183 192
184 const int bufsize = 16384; 193 const int bufsize = 16384;
185 char buffer[bufsize]; 194 char buffer[bufsize];
186 bool ok = TRUE; 195 bool ok = TRUE;
187 int bytesRead = 0; 196 int bytesRead = 0;
188 while ( ok && !sf.atEnd() ) { 197 while ( ok && !sf.atEnd() ) {
189 bytesRead = sf.readBlock( buffer, bufsize ); 198 bytesRead = sf.readBlock( buffer, bufsize );
190 if ( bytesRead < 0 ) 199 if ( bytesRead < 0 )
191 ok = FALSE; 200 ok = FALSE;
192 while ( ok && bytesRead > 0 ) { 201 while ( ok && bytesRead > 0 ) {
193 int bytesWritten = df.writeBlock( buffer, bytesRead ); 202 int bytesWritten = df.writeBlock( buffer, bytesRead );
194 if ( bytesWritten < 0 ) 203 if ( bytesWritten < 0 )
195 ok = FALSE; 204 ok = FALSE;
196 else 205 else
197 bytesRead -= bytesWritten; 206 bytesRead -= bytesWritten;
198 } 207 }
199 } 208 }
200 209
201 if ( ok ) 210 if ( ok )
202 ok = dest.writeLink(); 211 ok = dest.writeLink();
203 212
204 if ( ok ) { 213 if ( ok ) {
205 // okay now rename the file... 214 // okay now rename the file...
206 if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) { 215 if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) {
207 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 216 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
208 dest.file().latin1(), errno ); 217 dest.file().latin1(), errno );
209 // remove the tmp file, otherwise, it will just lay around... 218 // remove the tmp file, otherwise, it will just lay around...
210 QFile::remove( fn.latin1() ); 219 QFile::remove( fn.latin1() );
211 } 220 }
212 } else { 221 } else {
213 QFile::remove( fn.latin1() ); 222 QFile::remove( fn.latin1() );
214 } 223 }
215 224
216 return ok; 225 return ok;
217} 226}
218 227
228
229
219bool FileManager::copyFile( const QString & src, const QString & dest ) { 230bool FileManager::copyFile( const QString & src, const QString & dest ) {
220 bool success = true; 231 bool success = true;
221 struct stat status; 232 struct stat status;
222 int read_fd=0; 233 int read_fd=0;
223 int write_fd=0; 234 int write_fd=0;
224 struct stat stat_buf; 235 struct stat stat_buf;
225 off_t offset = 0; 236 off_t offset = 0;
226 QFile srcFile(src); 237 QFile srcFile(src);
227 QFile destFile(dest); 238 QFile destFile(dest);
228 239
229 if(!srcFile.open( IO_ReadOnly|IO_Raw)) { 240 if(!srcFile.open( IO_ReadOnly|IO_Raw)) {
230 return success = false; 241 return success = false;
231 } 242 }
232 read_fd = srcFile.handle(); 243 read_fd = srcFile.handle();
233 if(read_fd != -1) { 244 if(read_fd != -1) {
234 fstat (read_fd, &stat_buf); 245 fstat (read_fd, &stat_buf);
235 if( !destFile.open( IO_WriteOnly|IO_Raw ) ) 246 if( !destFile.open( IO_WriteOnly|IO_Raw ) )
236 return success = false; 247 return success = false;
237 write_fd = destFile.handle(); 248 write_fd = destFile.handle();
238 if(write_fd != -1) { 249 if(write_fd != -1) {
239 int err=0; 250 int err=0;
240 QString msg; 251 QString msg;
241 err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size); 252#ifdef Q_OS_MACX
242 if( err == -1) { 253#ifdef SENDMAIL
243 switch(err) { 254 /* FreeBSD does support a different kind of
244 case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. "; 255 * sendfile. (eilers)
245 case EINVAL: msg = "Descriptor is not valid or locked. "; 256 * I took this from Very Secure FTPd
246 case ENOMEM: msg = "Insufficient memory to read from in_fd."; 257 * Licence: GPL
247 case EIO: msg = "Unspecified error while reading from in_fd."; 258 * Author: Chris Evans
248 }; 259 * sysdeputil.c
249 success = false; 260 */
250 } 261 /* XXX - start_pos will truncate on 32-bit machines - can we
251 } else { 262 * say "start from current pos"?
263 */
264 off_t written = 0;
265 int retval = 0;
266 retval = sendfile(read_fd, write_fd, offset, stat_buf.st_size, NULL,
267 &written, 0);
268 /* Translate to Linux-like retval */
269 if (written > 0)
270 {
271 err = (int) written;
272 }
273#else /* SENDMAIL */
274 err == -1;
275 msg = "FAILURE: Using unsupported function \"sendfile()\" Need Workaround !!";
276 success = false;
277# warning "Need workaround for sendfile!!(eilers)"
278#endif /* SENDMAIL */
279
280#else
281 err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size);
282 if( err == -1) {
283 switch(err) {
284 case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. ";
285 case EINVAL: msg = "Descriptor is not valid or locked. ";
286 case ENOMEM: msg = "Insufficient memory to read from in_fd.";
287 case EIO: msg = "Unspecified error while reading from in_fd.";
288 };
289 success = false;
290 }
291#endif /* Q_OS_MACX */
292 if( !success )
293 qWarning( msg );
294 } else {
252 qWarning("open write failed %s, %s",src.latin1(), dest.latin1()); 295 qWarning("open write failed %s, %s",src.latin1(), dest.latin1());
253 success = false; 296 success = false;
254 } 297 }
255 } else { 298 } else {
256 qWarning("open read failed %s, %s",src.latin1(), dest.latin1()); 299 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
257 success = false; 300 success = false;
258 } 301 }
259 srcFile.close(); 302 srcFile.close();
260 destFile.close(); 303 destFile.close();
261 // Set file permissions 304 // Set file permissions
262 if( stat( (const char *) src, &status ) == 0 ) { 305 if( stat( (const char *) src, &status ) == 0 ) {
263 chmod( (const char *) dest, status.st_mode ); 306 chmod( (const char *) dest, status.st_mode );
264 } 307 }
265 308
266 return success; 309 return success;
267} 310}
268 311
269 312
270bool FileManager::renameFile( const QString & src, const QString & dest ) { 313bool FileManager::renameFile( const QString & src, const QString & dest ) {
271 if(copyFile( src, dest )) { 314 if(copyFile( src, dest )) {
272 if(QFile::remove(src) ) { 315 if(QFile::remove(src) ) {
273 return true; 316 return true;
274 } 317 }
275 } 318 }
276 return false; 319 return false;
277} 320}
278 321
279 322
280/*! 323/*!
281 Opens the document specified by \a f as a readable QIODevice. 324 Opens the document specified by \a f as a readable QIODevice.
282 The caller must delete the return value. 325 The caller must delete the return value.
283 326
284 Returns 0 if the operation fails. 327 Returns 0 if the operation fails.
285*/ 328*/
286QIODevice* FileManager::openFile( const DocLnk& f ) 329QIODevice* FileManager::openFile( const DocLnk& f )
287{ 330{
288 QString fn = f.file(); 331 QString fn = f.file();
289 QFile* fl = new QFile( fn ); 332 QFile* fl = new QFile( fn );
290 if ( !fl->open( IO_ReadOnly ) ) { 333 if ( !fl->open( IO_ReadOnly ) ) {
291 delete fl; 334 delete fl;
292 fl = 0; 335 fl = 0;
293 } 336 }
294 return fl; 337 return fl;
295} 338}
296 339
297/*! 340/*!
298 Opens the document specified by \a f as a writable QIODevice. 341 Opens the document specified by \a f as a writable QIODevice.
299 The caller must delete the return value. 342 The caller must delete the return value.
300 343
301 Returns 0 if the operation fails. 344 Returns 0 if the operation fails.
302*/ 345*/
303QIODevice* FileManager::saveFile( const DocLnk& f ) 346QIODevice* FileManager::saveFile( const DocLnk& f )
304{ 347{
305 QString fn = f.file(); 348 QString fn = f.file();
306 ensurePathExists( fn ); 349 ensurePathExists( fn );
307 QFile* fl = new QFile( fn ); 350 QFile* fl = new QFile( fn );
308 if ( fl->open( IO_WriteOnly ) ) { 351 if ( fl->open( IO_WriteOnly ) ) {
309 f.writeLink(); 352 f.writeLink();
310 } else { 353 } else {
311 delete fl; 354 delete fl;
312 fl = 0; 355 fl = 0;
313 } 356 }
314 return fl; 357 return fl;
315} 358}
316 359
317/*! 360/*!
318 Returns whether the document specified by \a f current exists 361 Returns whether the document specified by \a f current exists
319 as a file on disk. 362 as a file on disk.
320*/ 363*/
321bool FileManager::exists( const DocLnk &f ) 364bool FileManager::exists( const DocLnk &f )
322{ 365{
323 return QFile::exists(f.file()); 366 return QFile::exists(f.file());
324} 367}
325 368
326 369
327/*! 370/*!
328 Ensures that the path \a fn exists, by creating required directories. 371 Ensures that the path \a fn exists, by creating required directories.
329 Returns TRUE if successful. 372 Returns TRUE if successful.
330*/ 373*/
331bool FileManager::ensurePathExists( const QString &fn ) 374bool FileManager::ensurePathExists( const QString &fn )
332{ 375{
333 QFileInfo fi(fn); 376 QFileInfo fi(fn);
334 fi.setFile( fi.dirPath(TRUE) ); 377 fi.setFile( fi.dirPath(TRUE) );
335 if ( !fi.exists() ) { 378 if ( !fi.exists() ) {
336 if ( system(("mkdir -p "+fi.filePath())) ) 379 if ( system(("mkdir -p "+fi.filePath())) )
337 return FALSE; 380 return FALSE;
338 } 381 }
339 382
340 return TRUE; 383 return TRUE;
341} 384}