summaryrefslogtreecommitdiff
path: root/library
authorllornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
committer llornkcor <llornkcor>2003-07-17 02:25:08 (UTC)
commit6ca1d7605597f4b8a7559167e5cf3d6e093805cd (patch) (unidiff)
tree93096c3d0df0c0f02c75d2acc2f481120914945c /library
parent115e09bdeb2ee3c7c0b9344f95179e1d10e86e48 (diff)
downloadopie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.zip
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.gz
opie-6ca1d7605597f4b8a7559167e5cf3d6e093805cd.tar.bz2
fix filesaving when filename contains extended characters
Diffstat (limited to 'library') (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
@@ -25,12 +25,17 @@
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
@@ -53,29 +58,31 @@ FileManager::~FileManager()
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.
@@ -83,34 +90,33 @@ bool FileManager::saveFile( const DocLnk &f, const QByteArray &data )
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/*!
@@ -122,13 +128,13 @@ bool FileManager::saveFile( const DocLnk &f, const QString &text )
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 );
@@ -146,16 +152,16 @@ bool FileManager::loadFile( const DocLnk &f, QString &text )
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
@@ -164,67 +170,128 @@ bool FileManager::loadFile( const DocLnk &f, QByteArray &ba )
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/*!
@@ -236,15 +303,15 @@ QIODevice* FileManager::openFile( const DocLnk& f )
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/*!
@@ -263,12 +330,12 @@ bool FileManager::exists( const DocLnk &f )
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
@@ -35,14 +35,16 @@ public:
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: