summaryrefslogtreecommitdiff
authorllornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
committer llornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
commit6ca1d7605597f4b8a7559167e5cf3d6e093805cd (patch) (unidiff)
tree93096c3d0df0c0f02c75d2acc2f481120914945c
parent115e09bdeb2ee3c7c0b9344f95179e1d10e86e48 (diff)
downloadopie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.zip
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.gz
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.bz2
fix filesaving when filename contains extended characters
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--library/filemanager.cpp167
-rw-r--r--library/filemanager.h6
2 files changed, 121 insertions, 52 deletions
diff --git a/library/filemanager.cpp b/library/filemanager.cpp
index 2b97846..cc657fa 100644
--- a/library/filemanager.cpp
+++ b/library/filemanager.cpp
@@ -1,274 +1,341 @@
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>
32#include <sys/stat.h>
33#include <dirent.h>
34#include <sys/sendfile.h>
35#include <fcntl.h>
31 36
32/*! 37/*!
33 \class FileManager 38 \class FileManager
34 \brief The FileManager class assists with AppLnk input/output. 39 \brief The FileManager class assists with AppLnk input/output.
35*/ 40*/
36 41
37/*! 42/*!
38 Constructs a FileManager. 43 Constructs a FileManager.
39*/ 44*/
40FileManager::FileManager() 45FileManager::FileManager()
41{ 46{
42} 47}
43 48
44/*! 49/*!
45 Destroys a FileManager. 50 Destroys a FileManager.
46*/ 51*/
47FileManager::~FileManager() 52FileManager::~FileManager()
48{ 53{
49 54
50} 55}
51 56
52/*! 57/*!
53 Saves \a data as the document specified by \a f. 58 Saves \a data as the document specified by \a f.
54 59
55 Returns whether the operation succeeded. 60 Returns whether the operation succeeded.
56*/ 61*/
57bool FileManager::saveFile( const DocLnk &f, const QByteArray &data ) 62bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
58{ 63{
59 QString fn = f.file() + ".new"; 64 QString fn = f.file() + ".new";
60 ensurePathExists( fn ); 65 ensurePathExists( fn );
61 QFile fl( fn ); 66 QFile fl( fn );
62 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) 67 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) {
63 return FALSE; 68 qWarning("open failed");
69 return FALSE;
70 }
64 int total_written = fl.writeBlock( data ); 71 int total_written = fl.writeBlock( data );
65 fl.close(); 72 fl.close();
66 if ( total_written != int(data.size()) || !f.writeLink() ) { 73 if ( total_written != int(data.size()) || !f.writeLink() ) {
67 QFile::remove( fn ); 74 QFile::remove( fn );
68 return FALSE; 75 return FALSE;
69 } 76 }
77 qDebug("total written %d out of %d", total_written, data.size());
70 // else rename the file... 78 // else rename the file...
71 if ( ::rename( fn.latin1(), f.file().latin1() ) < 0 ) { 79 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) {
72 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 80 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
73 f.file().latin1(), errno ); 81 f.file().latin1(), errno );
74 // remove the file... 82 // remove the file...
75 QFile::remove( fn );
76 } 83 }
77 return TRUE; 84 return TRUE;
78} 85}
79 86
80/*! 87/*!
81 Saves \a text as the document specified by \a f. 88 Saves \a text as the document specified by \a f.
82 89
83 The text is saved in UTF8 format. 90 The text is saved in UTF8 format.
84 91
85 Returns whether the operation succeeded. 92 Returns whether the operation succeeded.
86*/ 93*/
87bool FileManager::saveFile( const DocLnk &f, const QString &text ) 94bool FileManager::saveFile( const DocLnk &f, const QString &text )
88{ 95{
89 QString fn = f.file() + ".new"; 96 QString fn = f.file() + ".new";
90 ensurePathExists( fn ); 97 ensurePathExists( fn );
91 QFile fl( fn ); 98 QFile fl( fn );
92 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) { 99 if ( !fl.open( IO_WriteOnly|IO_Raw ) ) {
93 qDebug( "open failed: %s", fn.latin1() ); 100 qWarning("open failed");
94 return FALSE; 101 return FALSE;
95 } 102 }
96 103
97 QCString cstr = text.utf8(); 104 QCString cstr = text.utf8();
98 int total_written; 105 int total_written;
99 total_written = fl.writeBlock( cstr.data(), cstr.length() ); 106 total_written = fl.writeBlock( cstr.data(), cstr.length() );
100 fl.close(); 107 fl.close();
101 if ( total_written != int(cstr.length()) || !f.writeLink() ) { 108 if ( total_written != int(cstr.length()) || !f.writeLink() ) {
102 QFile::remove( fn ); 109 QFile::remove( fn );
103 return FALSE; 110 return FALSE;
104 } 111 }
105 // okay now rename the file... 112 // okay now rename the file..
106 if ( ::rename( fn.latin1(), f.file().latin1() ) < 0 ) { 113 if ( !renameFile( fn.latin1(), f.file().latin1() ) ) {
107 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 114 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
108 f.file().latin1(), errno ); 115 f.file().latin1(), errno );
109 // remove the tmp file, otherwise, it will just lay around... 116
110 QFile::remove( fn.latin1() );
111 } 117 }
112 return TRUE; 118 return TRUE;
113} 119}
114 120
115 121
116/*! 122/*!
117 Loads \a text from the document specified by \a f. 123 Loads \a text from the document specified by \a f.
118 124
119 The text is required to be in UTF8 format. 125 The text is required to be in UTF8 format.
120 126
121 Returns whether the operation succeeded. 127 Returns whether the operation succeeded.
122*/ 128*/
123bool FileManager::loadFile( const DocLnk &f, QString &text ) 129bool FileManager::loadFile( const DocLnk &f, QString &text )
124{ 130{
125 QString fn = f.file(); 131 QString fn = f.file();
126 QFile fl( fn ); 132 QFile fl( fn );
127 if ( !fl.open( IO_ReadOnly ) ) 133 if ( !fl.open( IO_ReadOnly ) )
128 return FALSE; 134 return FALSE;
129 QTextStream ts( &fl ); 135 QTextStream ts( &fl );
130#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 136#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
131 // The below should work, but doesn't in Qt 2.3.0 137 // The below should work, but doesn't in Qt 2.3.0
132 ts.setCodec( QTextCodec::codecForMib( 106 ) ); 138 ts.setCodec( QTextCodec::codecForMib( 106 ) );
133#else 139#else
134 ts.setEncoding( QTextStream::UnicodeUTF8 ); 140 ts.setEncoding( QTextStream::UnicodeUTF8 );
135#endif 141#endif
136 text = ts.read(); 142 text = ts.read();
137 fl.close(); 143 fl.close();
138 return TRUE; 144 return TRUE;
139} 145}
140 146
141 147
142/*! 148/*!
143 Loads \a ba from the document specified by \a f. 149 Loads \a ba from the document specified by \a f.
144 150
145 Returns whether the operation succeeded. 151 Returns whether the operation succeeded.
146*/ 152*/
147bool FileManager::loadFile( const DocLnk &f, QByteArray &ba ) 153bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
148{ 154{
149 QString fn = f.file(); 155 QString fn = f.file();
150 QFile fl( fn ); 156 QFile fl( fn );
151 if ( !fl.open( IO_ReadOnly ) ) 157 if ( !fl.open( IO_ReadOnly ) )
152 return FALSE; 158 return FALSE;
153 ba.resize( fl.size() ); 159 ba.resize( fl.size() );
154 if ( fl.size() > 0 ) 160 if ( fl.size() > 0 )
155 fl.readBlock( ba.data(), fl.size() ); 161 fl.readBlock( ba.data(), fl.size() );
156 fl.close(); 162 fl.close();
157 return TRUE; 163 return TRUE;
158} 164}
159 165
160/*! 166/*!
161 Copies the document specified by \a src to the document specified 167 Copies the document specified by \a src to the document specified
162 by \a dest. 168 by \a dest.
163 169
164 Returns whether the operation succeeded. 170 Returns whether the operation succeeded.
165*/ 171*/
166bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest ) 172bool FileManager::copyFile( const AppLnk &src, const AppLnk &dest )
167{ 173{
168 QFile sf( src.file() ); 174 QFile sf( src.file() );
169 if ( !sf.open( IO_ReadOnly ) ) 175 if ( !sf.open( IO_ReadOnly ) )
170 return FALSE; 176 return FALSE;
171 177
172 QString fn = dest.file() + ".new"; 178 QString fn = dest.file() + ".new";
173 ensurePathExists( fn ); 179 ensurePathExists( fn );
174 QFile df( fn ); 180 QFile df( fn );
175 if ( !df.open( IO_WriteOnly|IO_Raw ) ) 181 if ( !df.open( IO_WriteOnly|IO_Raw ) )
176 return FALSE; 182 return FALSE;
177 183
178 const int bufsize = 16384; 184 const int bufsize = 16384;
179 char buffer[bufsize]; 185 char buffer[bufsize];
180 bool ok = TRUE; 186 bool ok = TRUE;
181 int bytesRead = 0; 187 int bytesRead = 0;
182 while ( ok && !sf.atEnd() ) { 188 while ( ok && !sf.atEnd() ) {
183 bytesRead = sf.readBlock( buffer, bufsize ); 189 bytesRead = sf.readBlock( buffer, bufsize );
184 if ( bytesRead < 0 ) 190 if ( bytesRead < 0 )
185 ok = FALSE; 191 ok = FALSE;
186 while ( ok && bytesRead > 0 ) { 192 while ( ok && bytesRead > 0 ) {
187 int bytesWritten = df.writeBlock( buffer, bytesRead ); 193 int bytesWritten = df.writeBlock( buffer, bytesRead );
188 if ( bytesWritten < 0 ) 194 if ( bytesWritten < 0 )
189 ok = FALSE; 195 ok = FALSE;
190 else 196 else
191 bytesRead -= bytesWritten; 197 bytesRead -= bytesWritten;
192 } 198 }
193 } 199 }
194 200
195 if ( ok ) 201 if ( ok )
196 ok = dest.writeLink(); 202 ok = dest.writeLink();
197 203
198 if ( ok ) { 204 if ( ok ) {
199 // okay now rename the file... 205 // okay now rename the file...
200 if ( ::rename( fn.latin1(), dest.file().latin1() ) < 0 ) { 206 if ( !renameFile( fn.latin1(), dest.file().latin1() ) ) {
201 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(), 207 qWarning( "problem renaming file %s to %s, errno: %d", fn.latin1(),
202 dest.file().latin1(), errno ); 208 dest.file().latin1(), errno );
203 // remove the tmp file, otherwise, it will just lay around... 209 // remove the tmp file, otherwise, it will just lay around...
204 QFile::remove( fn.latin1() ); 210 QFile::remove( fn.latin1() );
205 } 211 }
206 } else { 212 } else {
207 QFile::remove( fn.latin1() ); 213 QFile::remove( fn.latin1() );
208 } 214 }
209 215
210 return ok; 216 return ok;
211} 217}
212 218
219bool FileManager::copyFile( const QString & src, const QString & dest ) {
220 bool success = true;
221 struct stat status;
222 int read_fd=0;
223 int write_fd=0;
224 struct stat stat_buf;
225 off_t offset = 0;
226 QFile srcFile(src);
227 QFile destFile(dest);
228
229 if(!srcFile.open( IO_ReadOnly|IO_Raw)) {
230 return success = false;
231 }
232 read_fd = srcFile.handle();
233 if(read_fd != -1) {
234 fstat (read_fd, &stat_buf);
235 if( !destFile.open( IO_WriteOnly|IO_Raw ) )
236 return success = false;
237 write_fd = destFile.handle();
238 if(write_fd != -1) {
239 int err=0;
240 QString msg;
241 err = sendfile(write_fd, read_fd, &offset, stat_buf.st_size);
242 if( err == -1) {
243 switch(err) {
244 case EBADF : msg = "The input file was not opened for reading or the output file was not opened for writing. ";
245 case EINVAL: msg = "Descriptor is not valid or locked. ";
246 case ENOMEM: msg = "Insufficient memory to read from in_fd.";
247 case EIO: msg = "Unspecified error while reading from in_fd.";
248 };
249 success = false;
250 }
251 } else {
252 qWarning("open write failed %s, %s",src.latin1(), dest.latin1());
253 success = false;
254 }
255 } else {
256 qWarning("open read failed %s, %s",src.latin1(), dest.latin1());
257 success = false;
258 }
259 srcFile.close();
260 destFile.close();
261 // Set file permissions
262 if( stat( (const char *) src, &status ) == 0 ) {
263 chmod( (const char *) dest, status.st_mode );
264 }
265
266 return success;
267}
268
269
270bool FileManager::renameFile( const QString & src, const QString & dest ) {
271 if(copyFile( src, dest )) {
272 if(QFile::remove(src) ) {
273 return true;
274 }
275 }
276 return false;
277}
278
279
213/*! 280/*!
214 Opens the document specified by \a f as a readable QIODevice. 281 Opens the document specified by \a f as a readable QIODevice.
215 The caller must delete the return value. 282 The caller must delete the return value.
216 283
217 Returns 0 if the operation fails. 284 Returns 0 if the operation fails.
218*/ 285*/
219QIODevice* FileManager::openFile( const DocLnk& f ) 286QIODevice* FileManager::openFile( const DocLnk& f )
220{ 287{
221 QString fn = f.file(); 288 QString fn = f.file();
222 QFile* fl = new QFile( fn ); 289 QFile* fl = new QFile( fn );
223 if ( !fl->open( IO_ReadOnly ) ) { 290 if ( !fl->open( IO_ReadOnly ) ) {
224 delete fl; 291 delete fl;
225 fl = 0; 292 fl = 0;
226 } 293 }
227 return fl; 294 return fl;
228} 295}
229 296
230/*! 297/*!
231 Opens the document specified by \a f as a writable QIODevice. 298 Opens the document specified by \a f as a writable QIODevice.
232 The caller must delete the return value. 299 The caller must delete the return value.
233 300
234 Returns 0 if the operation fails. 301 Returns 0 if the operation fails.
235*/ 302*/
236QIODevice* FileManager::saveFile( const DocLnk& f ) 303QIODevice* FileManager::saveFile( const DocLnk& f )
237{ 304{
238 QString fn = f.file(); 305 QString fn = f.file();
239 ensurePathExists( fn ); 306 ensurePathExists( fn );
240 QFile* fl = new QFile( fn ); 307 QFile* fl = new QFile( fn );
241 if ( fl->open( IO_WriteOnly ) ) { 308 if ( fl->open( IO_WriteOnly ) ) {
242 f.writeLink(); 309 f.writeLink();
243 } else { 310 } else {
244 delete fl; 311 delete fl;
245 fl = 0; 312 fl = 0;
246 } 313 }
247 return fl; 314 return fl;
248} 315}
249 316
250/*! 317/*!
251 Returns whether the document specified by \a f current exists 318 Returns whether the document specified by \a f current exists
252 as a file on disk. 319 as a file on disk.
253*/ 320*/
254bool FileManager::exists( const DocLnk &f ) 321bool FileManager::exists( const DocLnk &f )
255{ 322{
256 return QFile::exists(f.file()); 323 return QFile::exists(f.file());
257} 324}
258 325
259 326
260/*! 327/*!
261 Ensures that the path \a fn exists, by creating required directories. 328 Ensures that the path \a fn exists, by creating required directories.
262 Returns TRUE if successful. 329 Returns TRUE if successful.
263*/ 330*/
264bool FileManager::ensurePathExists( const QString &fn ) 331bool FileManager::ensurePathExists( const QString &fn )
265{ 332{
266 QFileInfo fi(fn); 333 QFileInfo fi(fn);
267 fi.setFile( fi.dirPath(TRUE) ); 334 fi.setFile( fi.dirPath(TRUE) );
268 if ( !fi.exists() ) { 335 if ( !fi.exists() ) {
269 if ( system(("mkdir -p "+fi.filePath())) ) 336 if ( system(("mkdir -p "+fi.filePath())) )
270 return FALSE; 337 return FALSE;
271 } 338 }
272 339
273 return TRUE; 340 return TRUE;
274} 341}
diff --git a/library/filemanager.h b/library/filemanager.h
index f8d9425..61a3341 100644
--- a/library/filemanager.h
+++ b/library/filemanager.h
@@ -1,56 +1,58 @@
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#ifndef FILEMANAGER_H 20#ifndef FILEMANAGER_H
21#define FILEMANAGER_H 21#define FILEMANAGER_H
22 22
23#include <qstring.h> 23#include <qstring.h>
24#include <qstringlist.h> 24#include <qstringlist.h>
25 25
26class AppLnk; 26class AppLnk;
27class DocLnk; 27class DocLnk;
28class FileManagerPrivate; 28class FileManagerPrivate;
29 29
30class FileManager 30class FileManager
31{ 31{
32public: 32public:
33 FileManager(); 33 FileManager();
34 ~FileManager(); 34 ~FileManager();
35 35
36 bool saveFile( const DocLnk&, const QByteArray &data ); 36 bool saveFile( const DocLnk&, const QByteArray &data );
37 bool saveFile( const DocLnk&, const QString &text ); 37 bool saveFile( const DocLnk&, const QString &text );
38 bool loadFile( const DocLnk&, QByteArray &data ); 38 bool loadFile( const DocLnk&, QByteArray &data );
39 bool loadFile( const DocLnk&, QString &text ); 39 bool loadFile( const DocLnk&, QString &text );
40 bool copyFile( const AppLnk &src, const AppLnk &dest ); 40 bool copyFile( const AppLnk &src, const AppLnk &dest );
41 41 bool copyFile( const QString & src, const QString & dest );
42 // The caller must delete the return values. 42 bool renameFile( const QString &, const QString &);
43
44// The caller must delete the return values.
43 QIODevice* openFile( const DocLnk& ); 45 QIODevice* openFile( const DocLnk& );
44 QIODevice* saveFile( const DocLnk& ); 46 QIODevice* saveFile( const DocLnk& );
45 47
46 bool exists( const DocLnk& ); 48 bool exists( const DocLnk& );
47 49
48protected: 50protected:
49 bool ensurePathExists( const QString &fn ); 51 bool ensurePathExists( const QString &fn );
50 52
51private: 53private:
52 FileManagerPrivate *d; 54 FileManagerPrivate *d;
53}; 55};
54 56
55 57
56#endif 58#endif